<?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[ abstraction - 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[ abstraction - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 13 May 2026 22:45:02 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/abstraction/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ What is Abstraction in Coding? A Guide for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ I've met and talked to multiple new coders recently, and I see a common mistake they all seem to make. They don't embrace and understand abstractions in their code, or in their learning. But what are abstractions? And why are they important? Let's di... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-abstraction-in-coding/</link>
                <guid isPermaLink="false">66bc55f6da80a491ea5a5f65</guid>
                
                    <category>
                        <![CDATA[ abstraction ]]>
                    </category>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kealan Parr ]]>
                </dc:creator>
                <pubDate>Tue, 19 Mar 2024 22:29:31 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/EmbraceAbstractions-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I've met and talked to multiple new coders recently, and I see a common mistake they all seem to make.</p>
<p>They don't embrace and understand <strong>abstractions</strong> in their code, or in their learning.</p>
<p>But what are <strong>abstractions</strong>? And why are they important?</p>
<p>Let's dive in!</p>
<h2 id="heading-what-is-an-abstraction">What is an Abstraction?</h2>
<p>In coding, developers often use <strong>abstractions</strong> to simplify a system. <strong>Abstractions</strong> are a way of hiding complicated details from the end user, and trying to simplify whatever task you're trying to do.</p>
<p>But abstractions can be used in more than just code, so let's start with an example.</p>
<h3 id="heading-coffee-machine-abstractions">Coffee machine abstractions</h3>
<p>Imagine if you were creating a machine to make coffee for your users. There could be two approaches:</p>
<h4 id="heading-how-to-create-it-with-abstraction"><strong>How to Create it With Abstraction</strong></h4>
<ul>
<li>Have a button that says "Make coffee"</li>
</ul>
<h4 id="heading-how-to-create-it-without-abstraction"><strong>How to Create it Without Abstraction</strong></h4>
<ul>
<li>Have a button that says "Boil the water"</li>
<li>Have a button that says "Add the cold water to the kettle"</li>
<li>Have a button that says "Add 1 spoon of ground coffee to a clean cup"</li>
<li>Have a button that says "Clean any dirty cups"</li>
<li>And all the other buttons</li>
</ul>
<p>Can you see how, when we use abstraction, we don't expect the user to know how the machine makes coffee? But in the machine without abstraction, the user has to know in which order to press each button, which forces the user to understand how the coffee is made.</p>
<h2 id="heading-why-you-should-abstract-your-details">Why You Should Abstract Your Details</h2>
<p>When we use abstractions well, we make our system/codebase/task and so on much easier to understand and use. By hiding away complicated details inside a module, class, prototype, or function, we can make a super simple way to do complicated things.</p>
<p>So for example, let's say we have some complex code that ends up doing lots of complex, hard to understand math. We can wrap all that logic up in a function and provide a really easy interface where you just pass in your number and the function will do the work. </p>
<p>Developers in all languages and across all ecosystems make use of abstractions. The NodeJS team doesn't force you to understand how to modify 0's and 1's on a hard-drive to save text into a file – you can simply call the <code>writeFile</code> function.</p>
<p>When we use abstraction, we are essentially not forcing the person who uses our code to worry about the implementation details. They can just call the function and they'll get their answer back – they don't have to worry about what the function is doing "under the hood".</p>
<p><em>That's</em> the strength of abstracting details away in your code.  </p>
<p>I used to work at a company with a codebase that was 4 million lines long. Can you imagine a senior developer expecting me to understand every function? Every module? Every class? I would have NEVER merged a single change in that codebase if I did!</p>
<p>You can create a reusable, simple to understand, and easily changeable codebase by <strong>abstracting</strong> away certain details into the correct modules/separating out your code.</p>
<h2 id="heading-an-example-abstraction">An Example Abstraction</h2>
<p>Let's try and illustrate this with a code example.</p>
<p>Imagine you're working on a banking app, and you keep coming across this same weird subtraction over and over again, in different places in the code.</p>
<p><code>const res = bankAccountBalance - 1200</code></p>
<p><code>const res = bankAccountBalance – 1500</code></p>
<p><code>const res = bankAccountBalance - 1400</code></p>
<p>Why do we keep subtracting random numbers from everyone's bank balance once a year?! This is so unclear, there are zero comments explaining this?! What's happening? Is this an error?</p>
<p>Now imagine if this feature was clearer and did this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> minusFeesInUSDollars = <span class="hljs-function">(<span class="hljs-params">bankAccountBalance </span>) =&gt;</span> {
    <span class="hljs-comment">// Our yearly fees for this account are 1200 (USD)</span>
    <span class="hljs-keyword">const</span> YEARLY_FEES = <span class="hljs-number">1200</span>;
    <span class="hljs-keyword">return</span> bankAccountBalance - YEARLY_FEES;
}
<span class="hljs-keyword">const</span> minusFeesInGBPounds = <span class="hljs-function">(<span class="hljs-params">bankAccountBalance </span>) =&gt;</span> {
    <span class="hljs-comment">// Our yearly fees for this account are 1500 (GBP)</span>
    <span class="hljs-keyword">const</span> YEARLY_FEES = <span class="hljs-number">1500</span>;
    <span class="hljs-keyword">return</span> bankAccountBalance - YEARLY_FEES;
}
<span class="hljs-keyword">const</span> minusFeesInEuros = <span class="hljs-function">(<span class="hljs-params">bankAccountBalance </span>) =&gt;</span> {
    <span class="hljs-comment">// Our yearly fees for this account are 1400 (EUR)</span>
    <span class="hljs-keyword">const</span> YEARLY_FEES = <span class="hljs-number">1400</span>;
    <span class="hljs-keyword">return</span> bankAccountBalance - YEARLY_FEES;
}
</code></pre>
<p>The example isn't perfect, because we could remove some duplication in these functions – but we have abstracted logic into "something", in this case, a function.</p>
<h2 id="heading-why-should-i-embrace-abstractions">Why Should I Embrace Abstractions?</h2>
<p>I have explained <strong>abstractions</strong> so far in the context of code, but it can apply to your learning journey as well.</p>
<p>If you can't embrace <strong>abstractions</strong> (at least when you are starting) you will never be able to understand and excel as a developer.</p>
<p>Why is this the case?</p>
<p>Well, because there is always an <strong>abstraction</strong> beneath you, that you will be tempted to try and understand. This will ultimately frustrate you, overwhelm you, and <strong>kill your learning.</strong></p>
<p> Here's an example.</p>
<ol>
<li>You start to learn React.  </li>
</ol>
<p><em>This is going well! I'm starting to learn my first few bits of code and render some things to my computer screen. This is going well. 😊</em></p>
<ol start="2">
<li>You learn that React is a library of JavaScript.  </li>
</ol>
<p><em>Okay that's cool! I should learn a little bit of JavaScript before I start with React then. I'm going to stop learning React, and learn vanilla JavaScript first.</em></p>
<ol start="3">
<li>You learn JavaScript is a programming language made up of lots of different pieces.  </li>
</ol>
<p><em>Okay this is getting more complex now. There are JavaScript engines, third party API's, different runtimes. This is getting confusing.</em></p>
<ol start="4">
<li>You try to understand how an engine interprets JavaScript code.  </li>
</ol>
<p><em>Okay! So your JavaScript code is being run, by a piece of software coded in C++. What is C++?</em></p>
<ol start="5">
<li>You start to learn C++.  </li>
</ol>
<p><em>This learning journey isn't going so well anymore. This is starting to get very confusing and much longer.</em></p>
<ol start="6">
<li>You learn that C++ is simply an extension of C.   </li>
</ol>
<p><em>What on earth is C?!</em></p>
<p>...and so on.</p>
<p>If you continue to dig deeper and deeper and deeper, into every tiny little detail, you are much more likely to quit your learning journey, and it will only be because you feel overwhelmed.</p>
<p>And if by some miracle you haven't given up, you're going to spend a much, much longer time trying to learn some basic skills you might need for a job.</p>
<h2 id="heading-how-do-you-embrace-abstractions">How Do You Embrace Abstractions?</h2>
<p>As you're learning, you're going to have to get comfortable with not fully understanding some things in your learning journey.</p>
<p>You can just "abstract" this knowledge away, and stick to the things that are relevant to what you're currently doing.</p>
<p>Don't chase down every tiny little detail that you encounter if you are new in your learning journey. Truth is, even the experts don't know everything! They normally know lots of things in a narrow area.</p>
<h2 id="heading-one-day-you-can-dig-into-the-abstractions">One Day You Can Dig into the Abstractions</h2>
<p>I don't want this article to come across like I am saying you should never delve below the abstractions you use everyday. But what I am saying is it won't help you to delve into the abstractions <strong>before</strong> you have spent a decent time coding first.</p>
<p>You should try to learn things as you need to learn them if you are early in your journey to become a developer.</p>
<p>After all, learning to code is hard enough, without committing to learning the entire ecosystem before even understanding the basics.</p>
<p>Once you start to become comfortable in your learning journey, and want to improve your skills, <a target="_blank" href="https://www.hanselman.com/blog/please-learn-to-think-about-abstractions">then learn how your abstractions work</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this has been useful, and is encouraging if you are feeling overwhelmed with everything you're currently learning.</p>
<p>I tweet my articles <a target="_blank" href="https://twitter.com/kealanparr">here</a> if you would like to read more.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cloud Computing Abstractions – IaaS, PaaS, FaaS, and SaaS Explained ]]>
                </title>
                <description>
                    <![CDATA[ Abstracting is the process of reducing something to its most basic form. It is the hiding away of the inessential. For a drawing, this could be reducing it to its basic lines and shapes. Naturally, there are many levels of an abstraction, since what ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/cloud-computing-abstractions-explained/</link>
                <guid isPermaLink="false">66d45e0ad1ffc3d3eb89ddc5</guid>
                
                    <category>
                        <![CDATA[ abstraction ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud Computing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Adetunji ]]>
                </dc:creator>
                <pubDate>Tue, 16 May 2023 16:31:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/pictures-2.001-2.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Abstracting is the process of reducing something to its most basic form. It is the hiding away of the inessential.</p>
<p>For a drawing, this could be reducing it to its basic lines and shapes. Naturally, there are many levels of an abstraction, since what is inessential is subjective.</p>
<p>This is illustrated in the image below showing a Greek temple and two drawings at different levels of abstraction.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8cf1dcb-27a4-42fb-babb-b58fb8c659b3_1628x882.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Example of abstraction</em></p>
<p>As you abstract away more of the details of the temple, you are left with something very simple. In its most basic form, a Greek temple can be thought of as a triangle sitting on top of a rectangle with vertical lines going across the rectangle.</p>
<p>Abstractions are everywhere around us. Google Maps is a good example of this. You can have a satellite, roadmap, terrain, traffic, cycling, public transport or street view, among others. Each of these options abstracts away some details, allowing you to focus on what you want to see.</p>
<p>Even a satellite map is an abstraction, since it is a point in time snapshot and cannot capture every new house, tree, or blade of grass.</p>
<p>The key point is that an abstraction simplifies something by <strong>hiding away the underlying details.</strong> It is a way of managing complexity.</p>
<p>But there is always a price to be paid. In exchange for hiding away complexity, you lose some lower level details which often means a loss of control if things go wrong.</p>
<h1 id="heading-abstractions-in-the-cloud">Abstractions in the Cloud</h1>
<p>In cloud computing, abstractions are everywhere. When you choose a particular technology to solve a problem, you are implicitly choosing a level of abstraction.</p>
<p>There are four broad levels of abstraction in cloud computing. These are called the service models:</p>
<ul>
<li><p>IaaS (Infrastructure as a Service)</p>
</li>
<li><p>PaaS (Platform as a Service)</p>
</li>
<li><p>FaaS (Function as a Service)</p>
</li>
<li><p>SaaS (Software as a Service).</p>
</li>
</ul>
<p>These four broad service models are just a guide for splitting out the different levels of abstraction in cloud computing. You can think of them more like well thought-out opinions, rather than some hard rule of physics.</p>
<p>Some people only consider IaaS, PaaS and SaaS as the service models, ignoring FaaS. Others will include Container as a Service, Security as a Service, Database as a Service, and so on.</p>
<p>The examples can go on and on by simply appending “as a service” to different technologies. This makes sense since you can abstract at different levels, which makes any abstraction of the cloud a spectrum of possibilities.</p>
<p>Just like the Greek temple shown above, there can be many intermediary levels of abstraction between a life-like drawing of the temple and a drawing with a triangle sitting on top of a rectangle.</p>
<p>When you choose to use cloud computing instead of an on-premise solution, you are effectively choosing to abstract away some of the underlying tasks and pieces of infrastructure that you would otherwise need to manage.</p>
<p>The figure below shows the differences between an on-premise solution and IaaS, PaaS, FaaS, and SaaS.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f24811c-1b7f-4c93-b696-b42c5d41d576_1224x1080.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Figure illustrating the differences between an on-premise solution vs IaaS, PaaS, FaaS, and SaaS.</em></p>
<p>As you move to the right in the above illustration, you abstract away more of the underlying infrastructure stack. This reduces the complexity of what you are trying to build, since there are fewer things to build and manage.</p>
<p>But the price you pay for this reduction in complexity is a loss of control. Sometimes, that is a worthy price to pay, and sometimes it is not.</p>
<h2 id="heading-on-premise-solutions">On-Premise Solutions</h2>
<p>You are responsible for managing everything in the infrastructure stack, from the physical security of the data centre to the application itself.</p>
<p>In this case, almost nothing is abstracted away. This gives you increased control and flexibility to customise what you want. In exchange for that, you pay the price of managing the entire stack and bearing the risks associated with that.</p>
<p>This is analogous to opening a pizza restaurant, but instead of just renting some space, you build the restaurant from scratch.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a01e351-835d-4431-8298-de50ef3666d5_1886x1008.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Building a pizza restaurant from the ground up is like managing on-premise solutions</em></p>
<p>The upside is you have full control over how the restaurant will look. The downside is the large upfront expenditure you will need to make for plumbing, ventilation, electrical wiring, air conditioning, heating, and so on.</p>
<p>You will also be plagued with questions like “Is the restaurant big enough, or is it too big?” or “How do I expand or scale down based on growing or falling demand?”. Large upfront costs and higher levels of uncertainty are the price you pay for full control.</p>
<h2 id="heading-iaas-infrastructure-as-a-service"><strong>IaaS (Infrastructure as a Service)</strong></h2>
<p>The physical security, data centre infrastructure, networking, servers and virtualisation (the process of creating multiple virtual machines out of a physical server) is abstracted away and managed by the cloud provider.</p>
<p>You are responsible for managing the operating system and everything above it in the infrastructure stack. You still get to customise what virtual machine you want, based on the choices made available by the cloud provider, and you will pay to use the virtual machine on a pay-as-you-go basis.</p>
<p>You don’t have to worry about purchasing more servers or cooling requirements for your servers. All of that is abstracted away and managed for you.</p>
<p>Virtual machines/instances are a good example of IaaS – EC2 from AWS, Compute Engine from GCP, and VMs from Azure.</p>
<p>IaaS is analogous to simply renting some space for your pizza restaurant. The electrical wiring, plumbing, heating, and so on is abstracted away since it is managed by the owner of the building.</p>
<p>You are responsible for paying rent to use the space, hiring chefs, a manager, waiters and cleaners, buying equipment and furniture, choosing decor, building a menu, marketing and getting customers through the door.</p>
<p>Still a lot of work, but all of the non-pizza making activities are hidden away, allowing you to focus on doing what you do best – making pizza.</p>
<h2 id="heading-paas-platform-as-a-service"><strong>PaaS (Platform as a Service)</strong></h2>
<p>Here, you manage the runtime and everything above it. The runtime is a software environment that provides the necessary resources and services for an application to run. Examples include the Java Virtual machine for Java applications, Python runtime for Python applications, and Node.js for JavaScript applications.</p>
<p>With PaaS, you have abstracted away all of the physical infrastructure. All you need to worry about is your runtime.</p>
<p>Good examples of PaaS are AWS Beanstalk and GCP App Engine. Also, managed database services like AWS RDS and GCP Cloud SQL fall under PaaS.</p>
<p>PaaS is analogous to opening a franchise pizza restaurant. When you open a franchise, you are provided with a pre-built restaurant space, equipment, branding, and a set of processes to follow. You are responsible for the core activities of running the restaurant such as hiring staff, managing inventory, and creating menus.</p>
<p>PaaS works in a similar way, providing developers with a pre-built platform that abstracts away the underlying infrastructure, allowing them to focus on building and deploying applications.</p>
<h2 id="heading-faas-function-as-a-service"><strong>FaaS (Function as a Service)</strong></h2>
<p>Here, you manage the functions and the application while the cloud provider manages the rest.</p>
<p>What exactly is a function and how is it different from a runtime? A function is a block of code that performs a specific task, while a runtime is the environment in which that code is executed.</p>
<p>Functions are typically triggered by events such as HTTP requests, database updates, or messages from a queue. When an event occurs, the function is automatically executed, and the result is returned to the calling application.</p>
<p>This is analogous to hiring a freelance pizza chef to cook for you on-demand. When you hire this freelance chef, though, you only pay for the time they spend cooking. The chef starts getting paid in reaction to an event, that is the moment an order comes in, and stops getting paid once the pizza is ready. The rest of the time, the chef is just idle, waiting for the next order but not costing you any money.</p>
<p>Ignoring the corporate sleaze and potential illegality of such a practise, doing something like this will save you money since you are only paying for the duration of a pizza being made.</p>
<h2 id="heading-saas-software-as-a-service"><strong>SaaS (Software as a Service)</strong></h2>
<p>Here, you don’t manage anything, but simply consume the service offered. Prime Video, Gmail, and Outlook are great examples of SaaS. When you use these, you don’t care about how the application works. All of that is abstracted away. You simply access the software through a web browser or a mobile app and use as needed.</p>
<p>Drawing on the restaurant analogy, this can be compared to simply ordering a pizza from the restaurant. The restaurant abstracts all the the steps needed to make the pizza.</p>
<h1 id="heading-examples-of-iaas-paas-faas-amp-saas">Examples of IaaS, PaaS, FaaS &amp; SaaS</h1>
<p>The table below shows examples of IaaS, PaaS, FaaS and SaaS offerings from the main cloud providers – AWS, GCP &amp; Azure.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6ce9fab-512a-4d23-b7f7-0608e3042ec6_1524x970.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h1 id="heading-bringing-it-together-with-an-example">Bringing it Together with an Example</h1>
<p>If you are building a e-commerce site like Amazon.com, you will need a transactional database to store details about customers like their names, payment details, address, orders, inventories, and so on. How do you choose the right level of abstraction for your database?</p>
<p>You have four options to choose for you database. Starting from the option that abstracts the most from the infrastructure stack:</p>
<ol>
<li><p>You could choose the use a FaaS option like <a target="_blank" href="https://aws.amazon.com/rds/aurora/serverless/">AWS Aurora Serverless</a>. This automatically starts up the database when it is being used and shuts it down when not in use, allowing you to save money by only paying for when it's in use. This is ideal for an infrequently used database with unpredictable workloads</p>
</li>
<li><p>You could choose a PaaS option like <a target="_blank" href="https://aws.amazon.com/rds/">AWS RDS</a>. This is a managed database where AWS abstracts away and manages administrative tasks like OS patching, scaling, database backups and other admin tasks that would otherwise require a database admin (DBA) to manage</p>
</li>
<li><p>You could choose an IaaS option by installing a relational database management system (RDBMS) like MySQL on an EC2 instance. AWS will manage the hardware, but you will be responsible for managing the OS and the database application. So, admin tasks like OS patching, scaling, database backups, among others, will be your responsibility</p>
</li>
<li><p>You can choose an on premise solution. Here, you will self-host the database and manage the hardware yourself, in addition to all the database admin tasks as described above</p>
</li>
</ol>
<p>Which is the right option to choose? First, it depends on your use case and the benefits and tradeoffs you are comfortable with. This is trite but nevertheless true.</p>
<p>However, a good heuristic that will work most of the time for most problems is to focus on what to avoid. You generally want to avoid an extreme or outlier solution, unless the problem you are trying to solve is indeed extreme or an outlier. And most problems, by definition, cannot be outliers.</p>
<p>The FaaS option using Aurora, and the on premise solution are not ideal, unless your use case specifically demands the features that these options posses.</p>
<p>Aurora serverless is not a very popular service, so finding patterns for integration with other technologies or help with troubleshooting technical problems may be more difficult. Also, there can be some technical issues with using a serverless database like Aurora.</p>
<p>For example, waking it up from an idle state in response to a request can sometimes take a few seconds. And this can be a delay long enough to lose a customer on your e-commerce application.</p>
<p>The on premise solution is not ideal either, because an e-commerce application will have fluctuations in demand as a result of holidays, discounts or some product going viral. On premise solutions are bad at handling large fluctuations in demand.</p>
<p>This simple heuristic of focusing on what to avoid yields two acceptable solutions – the IaaS option of running your database on an EC2 instance or the PaaS option of using a managed database service like RDS. Either of these is fine for the use case described.</p>
<p>The key point to remember is that an abstraction simplifies something by <strong>hiding away the underlying details.</strong> It is a way of managing complexity.</p>
<p>The higher abstraction solution of using RDS is the less complex solution, since AWS manages all of the underlying complexities of OS patching, scaling, database backups and other admin tasks. The price you pay for this reduction in complexity is less control of the database and a higher AWS bill.</p>
<p>I hope this helps you choose the solution that's right for you. Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Abstraction in Programming? Explained for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ This article will not be a dry and boring explanation of abstract classes, interfaces, protocols, or similar software entities. I will explain what they are in simple terms, but my main goal is to change how you think about abstractions in general. A... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-abstraction-in-programming-for-beginners/</link>
                <guid isPermaLink="false">66d460d3c7632f8bfbf1e49d</guid>
                
                    <category>
                        <![CDATA[ abstraction ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ryan Michael Kay ]]>
                </dc:creator>
                <pubDate>Wed, 21 Dec 2022 18:08:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/12/smartphone-g7993a9917_1280-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This article will not be a dry and boring explanation of abstract classes, interfaces, protocols, or similar software entities.</p>
<p>I will explain what they are in simple terms, but my main goal is to change how you think about abstractions in general. All of this is in service of helping you develop the art of programming.</p>
<p>These are the topics I will cover:</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-an-abstraction">What is an abstraction?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-abstractions-in-your-programs">How to use abstractions in your programs</a><br>  – <a class="post-section-overview" href="#heading-how-to-use-interfaces-and-protocols">How to use interfaces and protocols</a><br>  – <a class="post-section-overview" href="#heading-how-to-use-function-types-and-lambda-expressions">How to use function types and lambda expressions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-is-abstraction-the-most-important-idea-in-programming">Is abstraction the most important idea in programming?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-much-abstraction-do-i-need">How much abstraction do I need?</a></p>
</li>
</ul>
<p>The code samples will be in Kotlin, but I have written the article assuming you only have basic programming knowledge in any industry standard language.</p>
<p>I also use a variety of approaches to cover both object-oriented and functional styles of code.</p>
<h2 id="heading-what-is-an-abstraction">What Is An Abstraction?</h2>
<p>To begin with, we will discuss what this term means in the most general sense. Here is a simplified definition I have come up with for an abstraction:</p>
<blockquote>
<p>“A <strong>less detailed representation</strong> of an object or concept in nature.”</p>
</blockquote>
<p>I know my definition sounds very vague, but we will discuss some clear examples shortly. First, we must understand what <strong>detail</strong> is.</p>
<h3 id="heading-what-is-detail">What Is Detail?</h3>
<p>Detail refers to the quantity, or density perhaps, of information. Here are two examples of data models which are more and less detailed:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">User</span> {
  <span class="hljs-type">name</span>,
  id
}
</code></pre>
<pre><code class="lang-pgsql"><span class="hljs-keyword">User</span> {
  <span class="hljs-type">name</span>: String,
  id: <span class="hljs-type">Integer</span>,
  phone: <span class="hljs-type">Integer</span>,
  email: String
}
</code></pre>
<p>There is no need to overthink this point! More details is another way of saying more information or more complexity.</p>
<p>The only other key point is to understand what a <strong>representation</strong> is.</p>
<h3 id="heading-how-to-represent-something">How to Represent Something</h3>
<p>Suppose you are going to travel somewhere which has a particularly deadly kind of venomous snake. In order to gain information about this snake, you have a few different options:</p>
<ul>
<li><p>Read a verbal description of the snake and its behaviour</p>
</li>
<li><p>Look at a drawing or picture of the snake</p>
</li>
<li><p>Listen to audio of what it sounds like when behaving aggressively</p>
</li>
</ul>
<p>All of the above points are examples of different kinds of representations, or abstractions, of the venomous snake.</p>
<p>In each case, some pieces of information, which accurately represent properties of the real snake, are conveyed. However, neither a verbal description, nor an image, nor a recording can bite you!</p>
<p>Here we see the main utility of abstractions: <strong>Conveying important information</strong> (also known as details or properties) of an object or concept, <strong>while leaving out the unnecessary information</strong>.</p>
<h2 id="heading-how-to-use-abstractions-in-your-programs">How to Use Abstractions In Your Programs</h2>
<p>Before we discuss some specifics, it is worth mentioning that everything in a computer program is technically an abstraction.</p>
<p>In fact, <strong>programming languages, as well as all forms of mathematics, are systems of abstractions</strong>.</p>
<p>However, programmers tend to think of abstractions as a narrow band of software entities usually referred to as:</p>
<ul>
<li><p>Interfaces or Protocols</p>
</li>
<li><p>Abstract Classes</p>
</li>
<li><p>Function Types/References/Signatures</p>
</li>
<li><p>Super/Parent-Classes</p>
</li>
</ul>
<p>Unfortunately, the names and mechanics of the above software entities can vary substantially in different programming languages.</p>
<p>For this reason, I will take two examples which may be more or less appropriate to your preferred languages:</p>
<ol>
<li><p>An interface or protocol (which will also cover abstract classes)</p>
</li>
<li><p>A function type or method reference</p>
</li>
</ol>
<p>In any case, don't worry so much about the names or any minor differences in how these things work across languages. Instead, I invite you to focus on the general ideas.</p>
<h2 id="heading-how-to-use-interfaces-and-protocols">How to Use Interfaces and Protocols</h2>
<p>I will use the term interface from here on, but this term is synonymous with protocol. I will also use the term function synonymously with method.</p>
<p>Interfaces allow you to define behaviour of functions, classes, or objects, without defining their implementation.</p>
<p>Don't worry, I am not like some teachers who throw out some jargon and pretend like I am teaching you something.</p>
<p>Let's look at exactly what I mean by behaviour and implementation.</p>
<p><strong>Behaviour</strong> literally means a function declaration:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserDataSource</span> </span>{
<span class="hljs-comment">//this line below has a function declaration but no function "body"</span>
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getUserById</span><span class="hljs-params">(id: <span class="hljs-type">String</span>)</span></span>: User?
}

<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>(
  <span class="hljs-keyword">val</span> id: String,
  <span class="hljs-keyword">val</span> someData: Any
)
</code></pre>
<p>You can see the footnotes below regarding my usage of the term “function declaration.”</p>
<p>To translate this into English, this function declaration says the we are defining a function which:</p>
<ul>
<li><p>Is named “getUserById”</p>
</li>
<li><p>Accepts a String type called “id” as an argument when called</p>
</li>
<li><p>Returns a “User” or a null value if no user exists (this is because we have a “?” after the “User” type)</p>
</li>
</ul>
<p><strong>Implementation</strong> refers to the function body:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//Note that ":" is short for extends/implements in Kotlin for the class</span>
<span class="hljs-comment">//declaration</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDatabase</span></span>(): UserDataSource {
<span class="hljs-comment">//the curly braces, and everything between them, is the implementation</span>
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getUserById</span><span class="hljs-params">(id: <span class="hljs-type">String</span>)</span></span>: User? {
    <span class="hljs-keyword">var</span> user: User? = <span class="hljs-literal">null</span>
    <span class="hljs-comment">//… not important for this example</span>
    <span class="hljs-keyword">return</span> user
  }
}
</code></pre>
<p>Another name for the function inside of the interface is an <em>abstract function</em>. Hopefully, our discussion on abstract meaning “<em>less detail</em>” is starting to make more sense here!</p>
<p><strong>Some notes for accuracy:</strong></p>
<ol>
<li><p>Some languages have features to define properties, variables, and even implementations (that is, function declarations + function bodies) within interfaces. This does not change the primary purpose of interfaces, though.</p>
</li>
<li><p>The term function declaration will be defined differently depending on the language. Instead of worrying about verbal definitions, please consider my code examples to follow what I mean.</p>
</li>
</ol>
<h3 id="heading-what-about-abstract-classes">What About Abstract Classes?</h3>
<p>Apart from in Python (and perhaps other languages I am not aware of), abstract classes are very similar to interfaces except for one key difference: a <strong>class may only inherit from a single abstract class.</strong></p>
<p>In my opinion, before languages started to include ways for interfaces to define their own implementations, the use of abstract classes versus interfaces was clear:</p>
<ul>
<li><p>If you only want to share behaviour across a set of software entities, use an interface</p>
</li>
<li><p>If you want to share implementation <strong>and</strong> behaviour, use an abstract class instead</p>
</li>
</ul>
<p>Unfortunately, this distinction is very blurry since many languages now have features to add implementation to interfaces (like Java’s Default Methods).</p>
<p>The only general recommendation I can make which does not account for the specific details of any particular programming language is this: Use the simplest construct to get the job done.</p>
<h2 id="heading-how-to-use-function-types-and-lambda-expressions">How to Use Function Types and Lambda Expressions</h2>
<p>There are different ways to achieve abstraction without defining interfaces or classes. But the amount of structure these language features require is still subject to language specifics.</p>
<p>Kotlin provides enough of these features that you will hopefully be able to make some connections with your preferred languages.</p>
<h3 id="heading-how-to-use-function-types-instead-of-an-interface">How to Use Function Types Instead Of An Interface</h3>
<p>We will start with a practical example and then explain the finer details part by part.</p>
<p>Suppose we want to set up an abstract function (recall that this means a function with no implementation) to handle a click event.</p>
<p>Using something like an interface, we could do the following:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">//assume this is an platform/OS component that tells you when</span>
<span class="hljs-comment">//a user clicks something on screen</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PlatformComponent</span></span>(
  <span class="hljs-keyword">var</span> clickListener: ClickListener? = <span class="hljs-literal">null</span>
) {
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">userClickedScreen</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">//Note: the "?" means handleClick() is only</span>
    <span class="hljs-comment">//called when clickListener is NOT NULL</span>
    clickListener?.handleClick()
  }
}
<span class="hljs-comment">//This interfaces hides (abstracts) the concrete class/type</span>
<span class="hljs-comment">//which handles the click</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ClickListener</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">handleClick</span><span class="hljs-params">()</span></span>
}
<span class="hljs-comment">//This concrete class/type handles the click</span>
<span class="hljs-comment">//by extending the interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ScreenController</span></span>() : ClickListener {
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">handleClick</span><span class="hljs-params">()</span></span> {
    println(<span class="hljs-string">"Click handled."</span>)
  }
}

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  PlatformComponent(
    ScreenController()
  ).userClickedScreen()
}
</code></pre>
<p>An alternative approach is to use a function type instead of an interface:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  <span class="hljs-keyword">val</span> controller = ScreenController()
  <span class="hljs-keyword">val</span> component = PlatformComponent(
    <span class="hljs-comment">//The double colon tells the compiler that we are referring to</span>
    <span class="hljs-comment">//the function handleClick defined in ScreenController</span>
    controller::handleClick
  )
  component.userClickedScreen()
}

<span class="hljs-comment">//assume this is an platform/OS component that tells</span>
<span class="hljs-comment">//you when a user clicks something on screen</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PlatformComponent</span></span>(
  <span class="hljs-keyword">var</span> clickListener: () -&gt; <span class="hljs-built_in">Unit</span>
) {
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">userClickedScreen</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">//This is equivalent to calling ScreenController.handleClick(),</span>
    <span class="hljs-comment">//but PlatformComponent does not know that. Abstraction!</span>
    clickListener()
  }
}
<span class="hljs-comment">//This concrete class/type handles the click</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ScreenController</span></span>() {
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">handleClick</span><span class="hljs-params">()</span></span> {
    println(<span class="hljs-string">"Click handled."</span>)
  }
}
</code></pre>
<p>In this example, we can see how there is even less structure required to achieve the same result. But keep in mind that having less structure does not immediately imply better code. Really, <strong>it depends</strong>.</p>
<p>In any case, with a practical example in mind, we can break down how this code actually works in more detail.</p>
<h3 id="heading-how-to-use-function-references">How to Use Function References</h3>
<p>If you are unfamiliar with how function types, method references (or whatever else they are called) work, this section explains them in Kotlin. Feel free to jump to the next section if you are already familiar.</p>
<p>Similar to most modern programming languages, we can create a reference variable to a particular function in Kotlin:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">var</span> clickListener: () -&gt; <span class="hljs-built_in">Unit</span>
</code></pre>
<p>In Kotlin, function types have the following syntax:</p>
<pre><code class="lang-kotlin">(optional list of parameter types) -&gt; <span class="hljs-keyword">return</span> type
</code></pre>
<p>For example:</p>
<ul>
<li><p><code>(Int, Int) -&gt; Int</code> means that the associated function must take in two Int parameters, and return a single Int</p>
</li>
<li><p><code>() -&gt; Unit</code> means that a function has no parameters and executes without returning a meaningful value</p>
</li>
</ul>
<p>Unit is roughly equivalent to Java’s void return type or Python’s None type – at least in principle.</p>
<p>When it comes time to call (invoke) a function reference, we have two options:</p>
<ul>
<li><p><code>clickListener()</code> for short</p>
</li>
<li><p><code>clickListener.invoke()</code> is the full syntax, which is necessary when making null-safe calls like <code>clickListener?.invoke()</code>, for example</p>
</li>
</ul>
<h3 id="heading-how-to-use-lambda-expressions">How to Use Lambda Expressions</h3>
<p>In the previous example, it is worth noting that ScreenController does not care what the actual function it is invoking happens to be named.</p>
<p>We can take this level of abstraction even further, by not even defining a ScreenController:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
  <span class="hljs-comment">//note that the outer parenthesis are optional in Kotlin,</span>
  <span class="hljs-comment">//but may make this easier to understand</span>
  <span class="hljs-keyword">val</span> component = PlatformComponent(
    { println(<span class="hljs-string">"Click handled."</span>) }
  )
  component.userClickedScreen()
}
<span class="hljs-comment">//assume this is an platform/OS component that tells</span>
<span class="hljs-comment">//you when a user clicks something on screen</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PlatformComponent</span></span>(
  <span class="hljs-keyword">var</span> clickListener: () -&gt; <span class="hljs-built_in">Unit</span>
) {
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">userClickedScreen</span><span class="hljs-params">()</span></span> {
    clickListener()
  }
}
</code></pre>
<p>Unlike the previous examples, this one is <strong>not intended to resemble a practical scenario</strong> – just to demonstrate a lambda expression.</p>
<p>The actual lambda expression is this:</p>
<p><code>{ println(“Click handled.”) }</code></p>
<p>As you can see, it does not get much more abstract than a lambda expression.</p>
<p>On the surface, it's almost like defining only the implementation but not the behaviour. But at least in Kotlin, the lambda expression must conform to the type we are assigning it to.</p>
<p>In this case, <code>{ println(“Click handled.”) }</code> has no parameters and does not return a meaningful value. So it conforms to <code>() -&gt; Unit</code>.</p>
<h3 id="heading-which-approach-should-i-use">Which Approach Should I Use?</h3>
<p>You may wonder which approach you should be using – assuming your language allows for multiple approaches.</p>
<p>The most accurate answer I can give you is that there is no general rule.</p>
<p>Plenty of teachers these days will say “<em>x</em> is worse than y” or simply “<em>x</em> is bad,” because it works great for clickbait and search engine optimization.</p>
<p>But a language, platform, code construct, architecture, and just about anything else can only be judged good, bad, better, or worse relative to your requirements.</p>
<p>In fact, different requirements are the reason we have languages as different as Python and Java which are both extremely popular.</p>
<p>So instead, try different approaches and be skeptical of anyone who makes absolute statements without discussing requirements.</p>
<h2 id="heading-is-abstraction-the-most-important-idea-in-programming">Is Abstraction the Most Important Idea in Programming?</h2>
<p>The point of this article was never to say: <em>“Using interfaces and abstract classes everywhere will make you a better programmer.”</em></p>
<p>In fairness, as many developers do, I went through a phase around 2016–2018 where I did actually think that statement was pretty accurate.</p>
<p>Instead, the point of this article is to explain two things:</p>
<ul>
<li><p>Abstraction in programming, in my opinion, <strong>should</strong> <strong>not specifically mean abstract classes, or any particular code construct</strong></p>
</li>
<li><p>Abstraction in programming is a <strong>process</strong> by which we design our software entities according to <strong>how much detail</strong> they internally (privately) contain and externally (publicly) provide</p>
</li>
</ul>
<p>In a sense, every decision we make about the structure of our code, regardless of the language, comes down to this process of abstraction.</p>
<p>With that being said, how do we know when making some aspect of our program more abstract is beneficial, useless, or detrimental?</p>
<h2 id="heading-how-much-abstraction-do-i-need">How Much Abstraction Do I Need?</h2>
<p>I can only think of one kind of situation where you should strongly consider using something like an interface or function type.</p>
<p>Recall that these software entities provide variability of implementation but consistent behaviour. Further, that implementation typically refers to the body of a function.</p>
<p>Two things follow from that observation:</p>
<ul>
<li><p>If no variability of implementation is required, there is not likely to be a benefit of using a more abstract software entity.</p>
</li>
<li><p>If variability of implementation is required, using a more abstract software entity is likely beneficial.</p>
</li>
</ul>
<p>We will now discuss two situations I have encountered where variability is a requirement.</p>
<h3 id="heading-how-to-make-your-code-easier-to-test">How to Make Your Code Easier to Test</h3>
<p>Suppose that we have some kind of software entity, which must request some user data from a database or network adapter:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PresentationLogic</span></span>(
 <span class="hljs-keyword">val</span> datasource: Datasource
) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">start</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">val</span> someData = datasource.getData()
        presentData(someData)
    }

    <span class="hljs-comment">//...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Datasource</span></span>() {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getData</span><span class="hljs-params">()</span></span>: Data {
        <span class="hljs-keyword">var</span> someData = getLocalOrRemoteData()
        <span class="hljs-comment">//... error handling and so on</span>

        <span class="hljs-keyword">return</span> someData
    }
}
</code></pre>
<p>Also suppose that we want to test <code>PresentationLogic</code> without needing a real datasource to supply the data.</p>
<p>There are a few different ways to solve this problem (see the note below), but a simple solution is to make the datasource more abstract:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PresentationLogic</span></span>(
 <span class="hljs-keyword">val</span> datasource: DatasourceInterface
) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">start</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">val</span> someData = datasource.getData()
        presentData(someData)
    }

    <span class="hljs-comment">//...</span>
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">DatasourceInterface</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getData</span><span class="hljs-params">()</span></span>: Data
}
</code></pre>
<p>From there, we can create a fake implementation of the datasource in a test environment:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeDatasource</span></span>(): DatasourceInterface {
        <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getData</span><span class="hljs-params">()</span></span>: Data {
            <span class="hljs-keyword">return</span> Data()
        }
}

<span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">testLogic</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> logic = PresentationLogic(
       <span class="hljs-comment">//here we provide the fake version</span>
       FakeDatasource()
    )
}
</code></pre>
<p>Using abstraction, PresentationLogic does not know or care whether it is talking to a fake or real datasource. By extension, it does not need to change to work with either of them. Variability of implementation!</p>
<p>Note that there are other way to achieve this variability apart from using an interface. You could use a mocking library, or configure a build tool to swap out implementations.</p>
<p>There is no clear answer to which approach is better outside of discussing specific requirements.</p>
<p>Also, note that this approach would not actually work unless the details of how the datasource is created are kept separate from <code>PresentationLogic</code>.</p>
<p>This is commonly referred to as Dependency Injection, which I will discuss in a separate article.</p>
<h3 id="heading-how-to-work-with-different-versions-and-vendors-of-a-service">How to Work With Different Versions and Vendors of a Service</h3>
<p>Suppose that for some reason, you must work with different versions or vendors of the same service depending on different requirements.</p>
<p>An example could be supporting both AWS and Firebase to store the same data. Another example could be supporting a legacy version of a service along with a newer version of that same service.</p>
<p>In any case, it is another situation where variability of implementation is expected.</p>
<p>The code examples we will discuss have the following requirements:</p>
<ul>
<li><p>A client program must use three services, all from different vendors, to perform the same behaviour</p>
</li>
<li><p>The decision to choose a particular service is determined at runtime based on the environment (platform, OS, hardware, and so on) of the client program</p>
</li>
</ul>
<p>For those wondering, “client” in this context is a generic word for some program or software entity which uses other programs or software entities.</p>
<p>For example, YouTube’s website and mobile apps are “client apps” of YouTube’s backend servers.</p>
<p>Without applying any abstraction, our client program will need to know about every possible service and be told which service to choose:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">clientProgram</span><span class="hljs-params">(
    request: <span class="hljs-type">Request</span>, 
    awsService: <span class="hljs-type">AwsService</span>,
    firebaseService: <span class="hljs-type">FirebaseService</span>,
    parseService: <span class="hljs-type">ParseService</span>
)</span></span>: Result {
    <span class="hljs-keyword">val</span> use: USE_SERVICE = determineBestService()

    <span class="hljs-keyword">val</span> result = <span class="hljs-keyword">when</span> (use) {
        USE_SERVICE.AWS -&gt; awsService.executeRequest(request)
        USE_SERVICE.FIREBASE -&gt; firebaseService.executeRequest(request)
        USE_SERVICE.PARSE -&gt; parseService.executeRequest(request)
    }

    <span class="hljs-comment">//assume additional work is done before returning the result</span>
    <span class="hljs-keyword">return</span> result
}

<span class="hljs-keyword">enum</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">USE_SERVICE</span> </span>{
    AWS,
    FIREBASE,
    PARSE
}
</code></pre>
<p>Notice that clientProgram has a parameter which refers to specific vendors of the service:</p>
<ul>
<li><p>Amazon Web Services (AWS)</p>
</li>
<li><p>Firebase</p>
</li>
<li><p>The now defunct Parse service from Facebook</p>
</li>
</ul>
<p>It follows that any changes to our services will require <code>clientProgram</code> to be refactored (rewritten) appropriately.</p>
<p>The reason I chose Parse as one of the example services is specifically because it was shut down, despite being widely used. There are various reasons why a particular service may no longer fit requirements, but not working any more is a good one.</p>
<p>An alternative approach would be to hide all the details about the service being used from clientProgram. You could use an interface, but for variety’s sake I have used a function type instead:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">//Creating the services</span>
    <span class="hljs-keyword">val</span> awsService = AwsService()
    <span class="hljs-keyword">val</span> firebaseService = FirebaseService()

    <span class="hljs-comment">//determining which service to use must </span>
    <span class="hljs-comment">//not be included in clientProgram</span>
    <span class="hljs-keyword">val</span> use: USE_SERVICE = determineBestService()

    <span class="hljs-comment">//Assign serviceToUse to the appropriate function</span>
    <span class="hljs-keyword">val</span> serviceToUse: (Request) -&gt; Result = <span class="hljs-keyword">when</span> (use) {
        USE_SERVICE.AWS -&gt; awsService::executeRequest
        USE_SERVICE.FIREBASE -&gt; firebaseService::executeRequest
    }

    <span class="hljs-keyword">val</span> request = getRequest()

    clientProgram(
       request,
       serviceToUse
    )
}


<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">clientProgram</span><span class="hljs-params">(
    request: <span class="hljs-type">Request</span>, 
    service: (<span class="hljs-type">Request</span>) -&gt; <span class="hljs-type">Result</span>
)</span></span>: Result {

    <span class="hljs-keyword">val</span> result = service.invoke(request)

    <span class="hljs-comment">//assume additional work is done before returning the result</span>

    <span class="hljs-keyword">return</span> result
}

<span class="hljs-keyword">enum</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">USE_SERVICE</span> </span>{
    AWS,
    FIREBASE
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AwsService</span></span>() {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">executeRequest</span><span class="hljs-params">(request: <span class="hljs-type">Request</span>)</span></span>: Result = Result()
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FirebaseService</span></span>() {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">executeRequest</span><span class="hljs-params">(request: <span class="hljs-type">Request</span>)</span></span>: Result = Result()
}
</code></pre>
<p>The end result of this abstraction is that we can change services without needing to change <code>clientProgram</code> – assuming our behaviour does not change.</p>
<p>I want to point out that I am not advocating that you hide every service behind some kind of abstraction. If no variability is required or expected, there may not be any benefit to extra abstraction.</p>
<h1 id="heading-closing-thoughts">Closing Thoughts</h1>
<p>I hope it is clear when reading this article that my intention is not to push dogmatic opinions about how abstract your code should be.</p>
<p>As a junior and intermediate developer, it took me a few years to realize that it really does depend on project requirements.</p>
<p>I also hope that this article gave you some new ideas and perspectives about what abstraction is and how it can be applied in your code. Good luck and happy coding!</p>
<h3 id="heading-before-you-go"><strong>Before you go...</strong></h3>
<p>If you liked this article and want more information on these principles and code constructs, check out my free, full length <a target="_blank" href="https://youtu.be/FL2SMZxNQlc">programming fundamentals course</a>. It includes professionally written English, Burmese, and Arabic subtitles.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
