<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: STX Next</title>
    <description>The latest articles on DEV Community by STX Next (@stx-next).</description>
    <link>https://dev.to/stx-next</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F5220%2Fb6b1c12f-39bc-4bd6-b836-2069f0899e60.jpg</url>
      <title>DEV Community: STX Next</title>
      <link>https://dev.to/stx-next</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stx-next"/>
    <language>en</language>
    <item>
      <title>Python vs. Node.js: Comparing the Pros, Cons, and Use Cases</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sun, 29 May 2022 12:38:59 +0000</pubDate>
      <link>https://dev.to/stx-next/python-vs-nodejs-comparing-the-pros-cons-and-use-cases-36c0</link>
      <guid>https://dev.to/stx-next/python-vs-nodejs-comparing-the-pros-cons-and-use-cases-36c0</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Adam Stempniak and Jacek Mirowski&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stxnext.com/ebooks/introduction-python-tech-managers/"&gt;We love Python&lt;/a&gt;—that much is clear.&lt;/p&gt;

&lt;p&gt;But is it a miracle drug to remedy all your software development challenges?&lt;/p&gt;

&lt;p&gt;No, it’s not. And if I were you, I’d be suspicious of anyone telling you otherwise.&lt;/p&gt;

&lt;p&gt;Whether it’s building software or doing just about anything in life, it’s rare that you can apply the same solution to every problem.&lt;/p&gt;

&lt;p&gt;Each software project comes with its own unique set of needs and requirements. &lt;a href="https://stxnext.com/ebooks/what-is-python-used-for/"&gt;What works&lt;/a&gt; for one may not work for another at all. At STX Next, we use whatever tech stack fits a given project best.&lt;/p&gt;

&lt;p&gt;That being said, comparisons are inevitable. After all, there are so many programming languages and frameworks to choose from that you can’t be faulted for wanting a little help in picking the one that is right for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stxnext.com/ebooks/python-vs-other-programming-languages/"&gt;Right alongside Python vs. Golang or Python vs. Java&lt;/a&gt;, one of the most popular queries we’ve seen lately is &lt;strong&gt;Node.js vs. Python&lt;/strong&gt;. We’re gonna shed some light on that.&lt;/p&gt;

&lt;p&gt;Read on for our in-depth look at Python and Node.js to learn their &lt;strong&gt;differences and similarities, strengths and weaknesses,&lt;/strong&gt; and most importantly: &lt;strong&gt;which is better?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Python and what is Node.js?
&lt;/h2&gt;

&lt;p&gt;Before we jump to specifics, we should clarify what it is we’re actually comparing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.stxnext.com/services/python-development/"&gt;Python&lt;/a&gt; is a programming language; Node.js is not. The language here is JavaScript, while Node.js is a runtime environment for JavaScript.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What this key difference between Python and Node.js means is that &lt;strong&gt;when you write in Node.js, you use the same language for both the frontend and the backend.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without further ado, here’s a more detailed breakdown of both choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the advantages of Python?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Python is much friendlier to junior developers
&lt;/h3&gt;

&lt;p&gt;Inexperienced Node.js developers can easily slow down development by making mistakes common to people who don’t fully understand some of the more advanced concepts and workings of &lt;a href="https://stxnext.com/services/javascript-development/"&gt;JavaScript.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This may be attributed to the way JavaScript has advanced over the years. Concepts like object-oriented programming received meaningful traction only after plenty of far less elegant code snippets and tutorials had spread online.&lt;/p&gt;

&lt;p&gt;Python, on the other hand, is very beginner-friendly, which is likely why it’s currently &lt;a href="https://cacm.acm.org/blogs/blog-cacm/176450-python-is-now-the-most-popular-introductory-teaching-language-at-top-u-s-universities/fulltext"&gt;the most popular introductory language at U.S. Universities.&lt;/a&gt; Most of the mistakes junior Python developers may make in some frameworks are more forgivable and less of a blocker moving forward.&lt;/p&gt;

&lt;h3&gt;
  
  
  Most Python frameworks don’t require a very high skill level from the developers
&lt;/h3&gt;

&lt;p&gt;A good example of that is Django, which has a mature ecosystem and allows you to write quality code fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python is more universal and versatile
&lt;/h3&gt;

&lt;p&gt;While it can also be used for desktop apps, thanks to &lt;a href="https://electronjs.org/"&gt;Electron&lt;/a&gt;, the main use case for Node.js is the web. The applications of Python, however, go far beyond the web.&lt;/p&gt;

&lt;p&gt;Python is a major contender to become &lt;a href="https://www.kaggle.com/surveys/2017"&gt;the leading programming language of data science.&lt;/a&gt; It’s a great asset to system administrators because it allows them to easily write small, one-off scripts, at the same time providing larger sysadmin tools like Ansible.&lt;/p&gt;

&lt;p&gt;For an example, look no further than Dropbox, one of the most common desktop apps written in Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python is simpler to use, better covered, and better documented
&lt;/h3&gt;

&lt;p&gt;This gives Python an edge over Node.js, even though both technologies are admittedly very fast to write in.&lt;/p&gt;

&lt;p&gt;Node.js is a JavaScript implementation, a language with a long history, and predominantly a frontend tool. Therefore, solutions found for Node.js online may be inadequate for backend use or rely on inaccessible interfaces.&lt;/p&gt;

&lt;p&gt;This cannot be overstated, since each JavaScript framework or runtime environment tends to have slight deviations in how it implements JavaScript. The situation has admittedly improved over the years, but it’s still a far cry from Python, where CPython, a single implementation, is used in the vast majority of Python projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the advantages of Node.js?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Node.js developers are more flexible
&lt;/h3&gt;

&lt;p&gt;Because we have the same language on the frontend and the backend, you need to be a JavaScript developer to use Node.js.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Node.js is a perfect tool if you want to rapidly develop your application. That's because you can use the same language (JavaScript) to develop the backend and the frontend sides of the app. Therefore, one programmer can implement the whole feature easily on their own, without the need to know another language. This also implies a reduction in development costs." &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;David Solomon, Node.js developer at STX Next&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This interdisciplinarity can come in handy when you least expect it, especially when there’s a fire you need to put out quickly.&lt;/p&gt;

&lt;p&gt;But let’s leave that eventuality aside for now. The fact remains that if you have solid project understanding and the right people to build it, you can’t go wrong with JavaScript and Node.js.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What I like about Node.js is that it uses the same language that I use on the frontend. This allows me to use the same libraries and tools (including TypeScript!) for both parts of my application, which results in a smaller tech stack. Additionally, I don't need to do almost any request data processing, as it is most often in JSON format, which is just JavaScript objects, ready to be used. That is what makes Node.js cooperation with frontend applications perfectly splendid." &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Przemysław Lewandowski, Senior JavaScript developer at STX Next&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The ecosystem of Node.js is less opinionated
&lt;/h3&gt;

&lt;p&gt;Many Node.js packages are simple, single-purpose libraries and microframeworks forcing developers to make more conscious decisions what to use and when.&lt;/p&gt;

&lt;p&gt;This makes Node.js more demanding and requires a higher level of advancement on the developers’ side than what it takes to write code in Python on top of Django, using built-in solutions for ORM, caching abstraction, and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  With Node.js, you can use JavaScript to code everything
&lt;/h3&gt;

&lt;p&gt;Node.js allows you to code both the frontend and the backend using JavaScript. This means you don’t need that many different technologies, which in turn means you don’t need your developers to learn yet another implementation of the same programming paradigms.&lt;/p&gt;

&lt;p&gt;At the stage of assembling the team, you often don’t know how many Python or JavaScript developers you’re going to need. Your needs also may differ in particular Sprints—if you’re working in Scrum, that is—depending on your goals.&lt;/p&gt;

&lt;p&gt;Using the same language for the whole project removes that risk from the equation. You can even share a part of the code between the front and the back. It’s a huge benefit, not having to waste time doing the same thing twice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Node.js community is large and JavaScript is one of the most dynamic and fastest-growing programming languages out there
&lt;/h3&gt;

&lt;p&gt;JavaScript has been growing at an exponential rate, &lt;a href="http://www.modulecounts.com/"&gt;with over 500 new packages being produced every day.&lt;/a&gt; Python no longer has the advantage of numerous libraries and frameworks it used to enjoy for many years, as JavaScript has caught up to it on that front by now.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What I like most about Node.js is that it's JavaScript. There is one language for the frontend and the backend. Another advantage of Node.js is that it's easy and popular, and it comes with plenty of packages, which actually also applies to Python." &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Bartosz Marciniec, Node.js developer at STX Next&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Alas, it’s not all sunshine and rainbows for JavaScript—but we’ll get to that in a second. First, an infographic!&lt;/p&gt;

&lt;h2&gt;
  
  
  Node.js vs. Python: an infographic
&lt;/h2&gt;

&lt;p&gt;Okay, let’s take a breather for a quick recap before we go on with our comparison of Python and Node.js.&lt;/p&gt;

&lt;p&gt;Here’s a visual summary of everything we’ve covered so far:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mSza3_wn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rtvga1umpell2vpgxat0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mSza3_wn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rtvga1umpell2vpgxat0.png" alt="Node.js vs Python - infographic" width="600" height="1500"&gt;&lt;/a&gt; There; all caught up!&lt;/p&gt;

&lt;p&gt;Let us now move on to discussing a particular issue that JavaScript—and, by extension, Node.js—is facing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems with JavaScript and Node.js
&lt;/h2&gt;

&lt;p&gt;JavaScript may be developing super fast now, but that wasn’t always the case.&lt;/p&gt;

&lt;p&gt;In the beginning, the language was &lt;strong&gt;written haphazardly&lt;/strong&gt;, and to this day it is still &lt;strong&gt;struggling with issues&lt;/strong&gt; caused by its old versions and their compatibility.&lt;/p&gt;

&lt;p&gt;JavaScript’s recent rise in popularity has brought with it another curious downside.&lt;/p&gt;

&lt;p&gt;So many developers have turned to the language in such a short period of time lately that it’s pretty &lt;strong&gt;difficult to keep up with all the new updates and tech intricacies.&lt;/strong&gt; &lt;a href="https://dayssincelastjavascriptframework.com/"&gt;See for yourself!&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The rapid growth of JavaScript libraries brings with it &lt;strong&gt;documentation problems,&lt;/strong&gt; which consequently results in &lt;strong&gt;poor quality&lt;/strong&gt; for Node.js. That is precisely why more skilled developers are necessary for the backend—handling it well requires more preparation beforehand.&lt;/p&gt;

&lt;p&gt;Sadly, this is nothing new for JavaScript; it’s actually quite typical. If history has taught us anything, it’s that Python has always been more reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should you especially consider when comparing Node.js and Python?
&lt;/h2&gt;

&lt;p&gt;Comparing technologies is always a challenge, and the question of Python vs. Node.js is no different.&lt;/p&gt;

&lt;p&gt;Here are 3 main points, each focusing on a different side of the story, that will help you make an informed decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trending technologies
&lt;/h3&gt;

&lt;p&gt;Python is perfectly suited for &lt;strong&gt;&lt;a href="https://www.stxnext.com/stx-new-blog/new-technologies-stx-next/"&gt;trending technologies&lt;/a&gt;, especially &lt;a href="https://stxnext.com/machine-learning-applications-examples-industries/"&gt;machine learning.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python is a major player in the world of data science and offers several &lt;a href="https://www.stxnext.com/stx-new-blog/blog/2018/09/20/most-popular-python-scientific-libraries/"&gt;tried and tested libraries that support ML.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;It’s easier to find &lt;a href="https://stxnext.com/services/machine-learning/"&gt;machine learning experts&lt;/a&gt; who are well versed in Python than JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/micropython/micropython"&gt;MicroPython&lt;/a&gt;—a lighter and smaller version of Python—can be run with less power and fewer resources, making it a perfect fit for IoT devices (JavaScript has an equivalent in the form of Espurino, but it’s significantly less popular).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;Node.js is more comfortable to use for the Internet of Things,&lt;/strong&gt; when you compare the most popular libraries for Python or JavaScript.&lt;/p&gt;

&lt;p&gt;As always, the choice is yours, and it depends on what you’re trying to build.&lt;/p&gt;

&lt;p&gt;Node.js allows you to &lt;strong&gt;use new technological trends earlier,&lt;/strong&gt; though it comes with a risk: you may need to rewrite your entire project later. &lt;strong&gt;For long-term projects, Python is far less risky.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why is that the case? Because the ecosystem of JavaScript seems like anarchy when compared to Python. Each JavaScript user is pulling in their own direction, in a sense, which results in &lt;strong&gt;substantial trend fluidity.&lt;/strong&gt; Because of that, technologies like Isomorphic JavaScript or Meteor become outdated much quicker.&lt;/p&gt;

&lt;p&gt;It’s different with Python. Significant changes are introduced slowly, sometimes incredibly so. What other way is there to call the 10-year-long support for Python 2.7?&lt;/p&gt;

&lt;p&gt;This instability and unpredictability of JavaScript is precisely why Python is the safer choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Speed and performance
&lt;/h3&gt;

&lt;p&gt;Here’s the thing about Node.js: &lt;strong&gt;it can’t do too many things at the same time unless you write very well in it.&lt;/strong&gt; Both Python and Node.js only pretend to be able to do a whole lot of stuff at once, but Python applications tend to use a simpler, more traditional multiprocessing model instead of a more advanced asynchronous paradigm.&lt;/p&gt;

&lt;p&gt;Use Node.js poorly, and you might easily end up with a &lt;strong&gt;slow-working, low-performance product.&lt;/strong&gt; If your project involves a particularly time-consuming task, it’ll put all the focus there while other functionalities will lag behind.&lt;/p&gt;

&lt;p&gt;When written correctly, your software will send information to the operating system that it needs to perform a certain function and move on, while the system works on that. But if you write that poorly, the app will wait for the system to complete that task, doing nothing else in the meantime.&lt;/p&gt;

&lt;p&gt;For the end user, &lt;strong&gt;this will seem like your software is slow.&lt;/strong&gt; Such problems notoriously occur when a lot of people use your product at the same time.&lt;/p&gt;

&lt;p&gt;A huge benefit of Python is that some of its frameworks are specifically designed to spare you the trouble. Granted, Django will also work slowly if written poorly, but it has &lt;strong&gt;built-in solutions to handle high load&lt;/strong&gt; that make it easier to prevent that outcome. That is only one of many instances when Python puts fewer technical expectations on the developers.&lt;/p&gt;

&lt;p&gt;The main difference is that Node.js is designed to use a small number of workers. This is why it may slow down easily when some of the workers hang. However, it may also perform much better due to not wasting time on context switching between them.&lt;/p&gt;

&lt;p&gt;The opposite approach is to use many workers. In this case, when some of them hang, the users served by the rest of them don’t suffer. &lt;a href="https://nodejs.org/api/worker_threads.html"&gt;The most recent Node.js releases also support worker threads,&lt;/a&gt; for CPU-bound workloads, though it is still an experimental feature.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Node.js is really good for developing real-time applications. It’s also quite easy to learn, which makes it straightforward to become a full-stack developer thanks to JavaScript. Unfortunately, Node.js is single-threaded so we have some cases when it’s not advisable to use that environment. Besides, Node.js is slow when we compare it to, for instance, Go."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Kacper Małkowski, Node.js developer at STX Next&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Team composition
&lt;/h3&gt;

&lt;p&gt;Like we said before, each project is special and has its own needs. You need to understand those needs to build it successfully.&lt;/p&gt;

&lt;p&gt;Truth is, &lt;strong&gt;Python is better suited for some projects and JavaScript for others.&lt;/strong&gt; Let’s not forget that building a software product is a fluid process. You often end up adapting your tech stack as you go along—usually the frameworks, but sometimes the language, too.&lt;/p&gt;

&lt;p&gt;However, &lt;strong&gt;the most important thing is your team composition.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do you have good &lt;a href="https://stxnext.com/services/python-development/"&gt;Python developers&lt;/a&gt;? Use Python!&lt;/p&gt;

&lt;p&gt;Do you have good &lt;a href="https://www.stxnext.com/services/nodejs-development/"&gt;Node.js developers&lt;/a&gt;? Use Node.js!&lt;/p&gt;

&lt;p&gt;Some team members work on one part of the project, some on the other. Sometimes team composition is decided upfront, but needs to be changed on the go, both on the frontend and the backend.&lt;/p&gt;

&lt;p&gt;Who you have on your team dictates both the choice of language and the choice of frameworks, above everything else.&lt;/p&gt;

&lt;p&gt;Naturally, the problem solves itself if you’re lucky enough to have full-stack developers with both Python and JavaScript on your team. Those, however, are in short supply and it’s much more common to be working with people who are well versed in one or the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is Python or Node.js better?
&lt;/h2&gt;

&lt;p&gt;Now, that’s the million-dollar question!&lt;/p&gt;

&lt;p&gt;Truth be told, the winner is… neither?&lt;/p&gt;

&lt;p&gt;We do get that you were hoping for a short-and-sweet takeaway to help you make your choice, so here it goes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you only have a group of junior developers with little experience on hand, go with Python; if your team is more skilled and accomplished, choose Node.js.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But there’s more to it than that.&lt;/p&gt;

&lt;p&gt;Even though Node.js favors seasoned players in the software engineering game, expert developers claim that it doesn’t actually offer them a whole lot in return. Yes, they need to call upon their expertise to use Node.js effectively, but it doesn’t really matter to them which of the two technologies they pick.&lt;/p&gt;

&lt;p&gt;So in the grand scheme of things, you could say that &lt;strong&gt;Python wins, because it doesn’t discriminate against junior developers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;However…&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts on Node.js and Python
&lt;/h2&gt;

&lt;p&gt;The bottom line is what the expert developers say: &lt;strong&gt;at the end of the day, it doesn't make that much of a difference whether you choose Python or Node.js.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.stxnext.com/stx-new-blog/beginners-introduction-python-frameworks/"&gt;Some Python frameworks, like asyncio,&lt;/a&gt; allow you to work in Python the same way you would in Node.js. It’s possible to make the experience really similar if you care about it enough.&lt;/p&gt;

&lt;p&gt;The journey may differ, but the destination can be very much the same. From a certain point of view, comparisons such as “Python vs. Node.js” are maybe just a little bit… pointless.&lt;/p&gt;

&lt;p&gt;Why? Because &lt;strong&gt;it all comes down to your team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The language and the frameworks you choose may not necessarily be better, but it won’t matter &lt;strong&gt;as long as you have the right people on the team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Talk to your team members. Ask them questions.&lt;/p&gt;

&lt;p&gt;How do they feel about the choice of language?&lt;/p&gt;

&lt;p&gt;Would they prefer to work in Python or Node.js?&lt;/p&gt;

&lt;p&gt;Don’t pay that much attention to tool selection; pay all the attention to team composition.&lt;/p&gt;

&lt;p&gt;Your team is what makes or breaks your software project.&lt;/p&gt;

</description>
      <category>python</category>
      <category>node</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>R vs. Python: What’s the Real Difference Between R and Python?</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sun, 22 May 2022 14:21:10 +0000</pubDate>
      <link>https://dev.to/stx-next/r-vs-python-whats-the-real-difference-between-r-and-python-3j35</link>
      <guid>https://dev.to/stx-next/r-vs-python-whats-the-real-difference-between-r-and-python-3j35</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Susan Johnson and Maciej Urbański&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The swift proliferation of data into our lives has resulted in the rise of tools used to analyze and extract valuable insights from this information. Python and R are the two most popular programming languages used to dissect data. If you’re venturing on a new data science project, choosing between them can be challenging.&lt;/p&gt;

&lt;p&gt;Both R and Python are state-of-the-art in terms of their orientation toward data science excellence, making it a tough decision to find the better option. If you use the Venn diagram to map the capabilities of the two languages, you will see a lot of convergence around the data-focused fields.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XFSiBA4T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nx81dx9yaoxjyfdgyf09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XFSiBA4T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nx81dx9yaoxjyfdgyf09.png" alt="Vienn diagram in Python vs R comparision" width="558" height="558"&gt;&lt;/a&gt;&lt;br&gt;
Nevertheless, Python and R have varying strengths and weaknesses. They also take a different approach to developing code and sharing results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning about both Python and R is obviously the ideal solution to choosing the right language. To help you do just that, we wrote this article. Below we’ll discuss:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;the differences and similarities of the two languages,&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;their advantages and disadvantages,&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;what the future has in store for them.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is R? What is R used for?
&lt;/h2&gt;

&lt;p&gt;Developed by Ross Ihaka and Robert Gentleman more than two decades ago, R is an open-source programming language and free software that possesses one of the richest ecosystems to perform statistical analysis and data visualization.&lt;/p&gt;

&lt;p&gt;R features a broad catalog of statistical and graphical methods, including linear regression, time series, machine learning algorithms, statistical inference, and more. Additionally, it offers complex data models and sophisticated tools for data reporting.&lt;/p&gt;

&lt;p&gt;Popular among data science scholars and researchers, there’s a library for almost every analysis you may wish to perform. In fact, the extensive array of libraries makes R the top choice for statistical analysis, particularly for specialized analytical work. Many multinational corporations (MNCs) use the R programming language, such as Facebook, Uber, Airbnb, Google, etc.&lt;/p&gt;

&lt;p&gt;Data analysis with R is completed in a few short steps—programming, transforming, discovering, modeling, and then communicating the results. When it comes to communicating the findings, this is where R truly stands out. R has a fantastic range of tools that allows sharing the results in the form of a presentation or a document, making reporting both elegant and trivial.&lt;/p&gt;

&lt;p&gt;Typically, R is used within RStudio—an &lt;a href="https://www.stxnext.com/blog/best-python-ides-code-editors/"&gt;integrated development environment (IDE)&lt;/a&gt; that simplifies statistical analysis, visualization, and reporting. But that’s not the only way to run R. For instance, R applications can be used directly and interactively on the web through Shiny.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Python? What is Python used for?
&lt;/h2&gt;

&lt;p&gt;Python is an object-oriented, general-purpose, and high-level programming language that was first released in 1989. It emphasizes code readability through its substantial use of white space. All in all, it was built in a way that it is comparatively intuitive to write and understand, &lt;a href="https://www.stxnext.com/what-is-python-used-for/"&gt;making Python an ideal coding language&lt;/a&gt; for those looking for quick development.&lt;/p&gt;

&lt;p&gt;Some of the world’s largest organizations—from NASA to Netflix, Spotify, Google, and more—leverage Python in some form to power their services. According to the &lt;a href="https://www.tiobe.com/tiobe-index/"&gt;TIOBE index&lt;/a&gt;, Python is the third most popular programming language in the world, only behind Java and C. Various reasons contribute to this achievement, including Python’s ease of use, its simple syntax, thriving community, and most importantly, versatility.&lt;/p&gt;

&lt;p&gt;Python can be used for various projects, from &lt;a href="https://www.stxnext.com/services/data-engineering/"&gt;data analytics&lt;/a&gt; and visualization to &lt;a href="https://www.stxnext.com/services/machine-learning/"&gt;artificial intelligence&lt;/a&gt;, language development, &lt;a href="https://www.stxnext.com/services/product-design/"&gt;design&lt;/a&gt;, and &lt;a href="https://www.stxnext.com/services/web-development/"&gt;web development&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Python is especially great for deploying machine learning at a large scale, as it has libraries with tools like TensorFlow, scikit-learn, and Keras, which enable the creation of sophisticated data models that can be plugged directly into a production system.&lt;/p&gt;

&lt;p&gt;Additionally, a lot of &lt;a href="https://www.stxnext.com/blog/most-popular-python-scientific-libraries/"&gt;Python libraries&lt;/a&gt; support data science tasks, like the ones listed below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Astropy&lt;/strong&gt;—a library featuring functionalities that are ideal for use in astronomy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Biopython&lt;/strong&gt;—a collection of non-commercial Python tools to represent biological sequences and sequence annotations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bokeh&lt;/strong&gt;—a Python interactive visualization library that helps create interactive plots, dashboards, and data applications quickly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DEAP&lt;/strong&gt;—a computation framework perfect for rapid prototyping and testing of ideas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Looking for more examples of useful Python scientific libraries? &lt;a href="https://www.stxnext.com/blog/most-popular-python-scientific-libraries/"&gt;Read all about them on our blog.&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  The differences between R and Python
&lt;/h2&gt;

&lt;p&gt;If you’re planning to choose either Python or R for your next software project, it’s essential that you know the different features of both languages so you can make an informed decision. Here are the primary differences between R and Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Learning curve
&lt;/h3&gt;

&lt;p&gt;Generally, the ease of learning would primarily depend on your background. &lt;/p&gt;

&lt;p&gt;R is quite hard for beginners to master due to its non-standardized code. The language looks clunky and awkward even to some experienced programmers. On the other hand, Python is easier and features a smoother learning curve, though statisticians often feel that this language focuses on seemingly unimportant things.&lt;/p&gt;

&lt;p&gt;So, the right programming language for your data science project will be the one that appears closer to the way of thinking about data you’re used to.&lt;/p&gt;

&lt;p&gt;For instance, if you prefer ease and time-efficiency over everything else, then Python might seem more appealing to you. The language demands less coding time, thanks to its syntax that’s similar to the English language.&lt;/p&gt;

&lt;p&gt;It’s a running joke that the only thing that pseudo-code needs to become a Python program is saving it in a .py file. This allows you to get your tasks done quickly, in turn giving you more time to work with Python. Additionally, R’s coding requires an extended learning period.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Popularity
&lt;/h3&gt;

&lt;p&gt;Python and R are both popular. However, Python is used by a broader audience than R. R in comparison to Python is considered a niche programming language. Many organizations, as stated earlier, use Python for their production systems.&lt;/p&gt;

&lt;p&gt;R, on the other hand, is generally used in the academia and research industry. Though industry users favor Python, they are starting to consider R due to its prowess in data manipulation.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Packages
&lt;/h3&gt;

&lt;p&gt;Both R and Python offer thousands of open-source packages you can readily use in your next project.&lt;/p&gt;

&lt;p&gt;R puts forward a CRAN and hundreds of alternative packages to perform a single task, but they are less standardized. As a result, the API and its usage greatly varies, making it hard to learn and combine.&lt;/p&gt;

&lt;p&gt;Additionally, the authors of highly specialized packages in R are often scientists and statisticians and not programmers. This means the outcome is simply a set of specialized tools designed for a specific purpose, such as DNA sequencing data analysis or even broadly defined statistical analysis.&lt;/p&gt;

&lt;p&gt;However, R’s packages are less mix-and-match than Python’s. Currently, some attempts are being made to orchestrate suites of tools, like tidyverse, which gather packages working well together and using similar coding standards. When it comes to Python, its packages are more customizable and efficient, but they’re typically less specialized toward data analysis tasks.&lt;/p&gt;

&lt;p&gt;Nevertheless, Python does feature some solid tools for data science like scikit-learn, Keras (ML), TensorFlow, pandas, NumPy (data manipulations), matplotlib, seaborn, and plotly (visualizations). R, on the other hand, has caret (ML), tidyverse (data manipulations), and ggplot2 (excellent for visualizations).&lt;/p&gt;

&lt;p&gt;Furthermore, R has Shiny for rapid app deployment, while with Python, you will have to put in a bit more effort. Python also has better tools for integrations with databases than R, most importantly Dash.&lt;/p&gt;

&lt;p&gt;In simple words, Python will be the ideal choice if you’re planning to build a full-fledged application, though both choices are good for a proof of concept. R comes with specialized packages for statistical purposes, and Python is not nearly as strong in this particular field. Additionally, R is very good at manipulating data from most popular data stores.&lt;/p&gt;

&lt;p&gt;Another aspect worth mentioning here is maintainability. Python allows you to create, use, destroy, and duplicate a wild and vibrant menagerie of environments, each with different packages installed. With R, this happens to be a challenge, only exacerbated by package incompatibilities.&lt;/p&gt;

&lt;p&gt;Experts often use Jupyter Notebook, a popular tool for scripting, rapid exploration, and sketch-like code development iterations. It supports kernels of both R and Python, but it’s worth mentioning that the tool itself was written and originated in the Python ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Visualizations
&lt;/h3&gt;

&lt;p&gt;R was explicitly created for data analysis and visualization. Hence, its visualizations are easier on the eyes than Python’s extensive visualization libraries that make visualizations complex. In R, ggplot2 makes customizing graphics far simpler and more intuitive than in Python with Matplotlib.&lt;/p&gt;

&lt;p&gt;However, you can overcome this issue with Python using the Seaborn library that offers standard solutions. Seaborn can help you achieve similar plots to ggplot2 with relatively fewer lines of code.&lt;/p&gt;

&lt;p&gt;Overall, there are disagreements about which programming language is better for creating plots efficiently, clearly, and intuitively. The ideal software for you will depend on your individual programming language preferences and experience. At the end of the day, you can leverage both Python and R to visualize data clearly, but Python is more suited for deep learning than data visualization.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Speed and performance
&lt;/h3&gt;

&lt;p&gt;Python is a high-level programming language, meaning it’s the perfect choice if you’re planning to build critical applications fast. On the other hand, R often requires longer code for even simple processes. This significantly increases development time.&lt;/p&gt;

&lt;p&gt;When it comes to execution speed, the difference between Python and R is minute. Both programming languages are capable of handling big data operations.&lt;/p&gt;

&lt;p&gt;Though either R or Python aren’t as fast as some compiled programming languages, they circumvent this issue by allowing C/C++-based extensions. Additionally, communities of both languages have implemented data-managing libraries leveraging this feature.&lt;/p&gt;

&lt;p&gt;This means data analysis in Python and R can be done at C-like speed without losing expressivity or dealing with memory management and other low-level programming concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python vs. R: Advantages and disadvantages
&lt;/h2&gt;

&lt;p&gt;Both Python and R have pros and cons. A few of them are noticeable, while others can easily be missed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of R
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;R is a comfortable and clear language for professional programmers, since it was mainly created for data analysis. Therefore, most specialists are familiar with how the language works.&lt;/li&gt;
&lt;li&gt;Checking statistical hypotheses only takes a few lines of code with R, as many functions necessary for data analysis come as built-in language functions. (But remember that this does come at the cost of customizability.)&lt;/li&gt;
&lt;li&gt;RStudio (IDE) and other essential data processing packages are easy to install.&lt;/li&gt;
&lt;li&gt;R has many data structures, parameters, and operators that involve many things—from arrays to matrices, recursion, and loops alongside integration with other programming languages like Fortran, C, and C++.&lt;/li&gt;
&lt;li&gt;R is primarily used for statistical computations. One of its primary highlights is a set of algorithms for machine learning engineers and consultants. In addition, it is used for classification, linear modeling, time series analysis, clustering, and more.&lt;/li&gt;
&lt;li&gt;R puts forward an efficient package repository and an extensive array of ready-made tests for almost all types of data science and machine learning.&lt;/li&gt;
&lt;li&gt;There are multiple quality packages for data visualization for various tasks. For example, users can build two-dimensional graphics and three-dimensional models.&lt;/li&gt;
&lt;li&gt;Basic statistical methods are executed as standard functions that boost the development speed.&lt;/li&gt;
&lt;li&gt;With R, you can find numerous additional packages for every taste—whether you want a package with data from Twitter or one for modeling pollution levels. Every day, more and more packages reach the market, and all of them are collected under a single roof: the special CRAN repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages of R
&lt;/h3&gt;

&lt;p&gt;Like any other programming language, R comes with a few disadvantages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Typically, the R programming language offers low performance, though you’ll still be able to find packages in the system that allow a developer to improve the speed.&lt;/li&gt;
&lt;li&gt;Compared to other programming languages, R is highly specialized, meaning skills in it can’t be as easily applied to other fields than data processing.&lt;/li&gt;
&lt;li&gt;As most of the code in R is written by people who aren’t familiar with programming, the readability of quite a few programs is questionable. After all, not every user sticks to the guidelines of proper code design.&lt;/li&gt;
&lt;li&gt;R is the perfect tool for statistics and standalone applications. However, it doesn’t work that well in areas where traditional general-purpose languages are used.&lt;/li&gt;
&lt;li&gt;You can use the same functionalities of R in various ways, but the syntax for several tasks isn’t entirely obvious.&lt;/li&gt;
&lt;li&gt;As there’s an extensive number of R libraries, the documentation of a few less popular ones can’t be considered complete.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advantages of Python
&lt;/h3&gt;

&lt;p&gt;Python is widely used for its simplicity, but that doesn’t mean it has low functionality.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Being a multipurpose language, Python is great for data processing. The language comes in handy there especially because it facilitates easy development of a data processing pipeline where the results are incorporated into web applications.&lt;/li&gt;
&lt;li&gt;Programmers find Python particularly beneficial due to its interactivity that’s crucial for testing hypotheses interactively in data science.&lt;/li&gt;
&lt;li&gt;Python is being actively developed. With every new version, the performance and syntax keep improving. For instance, version 3.8 featured a new walrus operator, which is quite the event when it comes to any language. In other languages like Java and C++, the rate of change is comparatively slower—changes need to be approved by a special committee that holds meetings every few years. Python changes are proposed by PEPs, and make it into the language often even after a single release cycle, which is one year. In simple words, this means Python is evolving faster than R.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages of Python
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When it comes to choosing software for data analysis, visualization is a vital capability you should consider. However, while Python has an extensive list of libraries for visualization, choosing a single option can be too overwhelming. Furthermore, visualization in Python is often more complicated than in R, and its results are also not entirely clear sometimes.&lt;/li&gt;
&lt;li&gt;Python lacks alternatives for most R libraries, which makes statistical data analysis and/or R-to-Python conversion challenging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The future of Python and R
&lt;/h2&gt;

&lt;p&gt;As far as programming languages go, there’s no denying that Python is hot. Though it was created as a general-purpose scripting language, Python quickly evolved to be the most popular language for data science. Some even began to suggest that R is doomed and destined to eventually be replaced completely by Python.&lt;/p&gt;

&lt;p&gt;However, while Python might appear to be consuming R, the R language is far from dead. Regardless of what the naysayers claim, R is making a furious comeback into the data science arena. The popularity indexes continue to show this programming language’s repeated resurgence and prove that it’s still a strong candidate to consider in data science projects.&lt;/p&gt;

&lt;p&gt;Ever since its advent, R has consistently risen in popularity in the world of data science. From its #73 spot in December 2008, R became the 14th most popular language in August 2021 on the &lt;a href="https://www.tiobe.com/tiobe-index/"&gt;TIOBE index&lt;/a&gt;. On the other hand, Python took over the second position from Java this year, hitting an 11.86% popularity rating. Meanwhile, R had a popularity rating of 1.05%, a decrease of 1.75% from the previous year.&lt;/p&gt;

&lt;p&gt;“Although R is still used by academics and data scientists, companies interested in data analytics are turning to Python for its scalability and ease of use,” Nick Kolakowski, senior editor at Dice Insights, said. “Relying on usage by a handful of academics and nobody else might not be enough to keep R alive. That’s not viable,” he wrote.&lt;/p&gt;

&lt;p&gt;Similarly, Martijn Theuwissen, the co-founder of DataCamp, admits that Python has momentum. However, he denies the assertion that R is dead or dying. According to him, “Reports of R’s decline are greatly exaggerated. If you look at the growth of R, it’s still growing. Based on what I observe, Python is growing faster.”&lt;/p&gt;

&lt;p&gt;Many other data points also suggest that Python’s success over the years has come at the expense of R. Nevertheless, measuring the popularity of a language is an extremely difficult task. Almost every language has a natural life, and there is no foolproof way to pinpoint when their lifecycle might end. In the end, there is no way to predict the exact future of any given language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary and final thoughts on R vs. Python
&lt;/h2&gt;

&lt;p&gt;Python and R are both high-level, open-source programming languages that are among the most popular for data science and statistics. Nevertheless, R tends to be the right fit for traditional statistical analysis, while Python is ideal for conventional data science applications.&lt;/p&gt;

&lt;p&gt;Python is a simple, well-designed, and powerful language that was created with web development in mind. However, it is still efficient at data science projects.&lt;/p&gt;

&lt;p&gt;Python is relatively easy to learn, as it focuses on simplicity. So, provided you have access to the right tools and libraries, the language can effortlessly take you from statistics to data science and beyond to a full-fledged production app. In fact, this is one of the most significant advantages of using Python.&lt;/p&gt;

&lt;p&gt;Furthermore, unlike with other programming languages like JavaScript, the choice of frameworks isn’t too overwhelming with Python. Therefore, you’ll be able to create a practical and reliable toolbox without worrying you aren’t using the latest tech.&lt;/p&gt;

&lt;p&gt;On the other hand, R’s most significant advantage is the presence of highly specialized packages that can take you effortlessly through the not-so-customizable pipelines of data manipulation. However, R was created for statistical computing, and people without prior experience find it hard to work with the language initially.&lt;/p&gt;

&lt;p&gt;Even so, there are instances where you can use a combination of both languages. For instance, you can use R in Python code through r2py. This is particularly beneficial when you’re outsourcing computation to R.&lt;/p&gt;

&lt;p&gt;If you’re interested in learning more about Python, here are a few of our resources that can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.stxnext.com/python-vs-other-programming-languages/"&gt;Python vs. Other Programming Languages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stxnext.com/what-is-python-used-for/"&gt;What Is Python Used for?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stxnext.com/blog/top-10-blogs-python/"&gt;Top 10 Blogs to Get You Started on Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stxnext.com/blog/how-to-audit-the-quality-of-your-python-code"&gt;How to Audit the Quality of Your Python Code: A Step-by-Step Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>r</category>
      <category>programming</category>
    </item>
    <item>
      <title>Python vs. Java: Comparing the Pros, Cons, and Use Cases</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sat, 21 May 2022 22:57:37 +0000</pubDate>
      <link>https://dev.to/stx-next/python-vs-java-comparing-the-pros-cons-and-use-cases-2al</link>
      <guid>https://dev.to/stx-next/python-vs-java-comparing-the-pros-cons-and-use-cases-2al</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Adam Stempniak&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Some battles seem unwinnable and have apparently been raging forever.&lt;/p&gt;

&lt;p&gt;Star Wars vs. Star Trek. Cats vs. dogs. Apple vs. Samsung.&lt;/p&gt;

&lt;p&gt;But when it comes to software development, different conflicts tend to come up:&lt;/p&gt;

&lt;p&gt;Quality vs. time. Time vs. cost. Cost vs. quality.&lt;/p&gt;

&lt;p&gt;These concerns play a key role in &lt;a href="https://stxnext.com/ebooks/what-is-python-used-for/"&gt;choosing the programming language&lt;/a&gt; for your project, which is one of the first major decisions you have to make.&lt;/p&gt;

&lt;p&gt;As a Python software house, we are intimately familiar with the challenge of &lt;a href="https://stxnext.com/ebooks/python-vs-other-programming-languages/"&gt;contrasting Python with other languages&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.stxnext.com/stx-new-blog/go-go-python-rangers-comparing-python-and-golang/py"&gt;Python vs. Golang&lt;/a&gt;. &lt;a href="https://www.stxnext.com/blog/python-vs-nodejs-comparison/"&gt;Python vs. Node.js&lt;/a&gt;. Python vs. Java.&lt;/p&gt;

&lt;p&gt;In this article, we’ll focus on the last one.&lt;/p&gt;

&lt;p&gt;Granted, such comparisons aren’t as set in stone as they may appear. It’s usually a little more complicated than a cut-and-dry list of pros and cons.&lt;/p&gt;

&lt;p&gt;For example, building an MVP in Java can take months, while &lt;a href="https://www.stxnext.com/services/python-development/"&gt;Python&lt;/a&gt; gets you the same results in weeks. And yet, Java is still popular with big banks and fintechs. Are they justified in their choice?&lt;/p&gt;

&lt;p&gt;There’s a lot more to the story. Each language has different use cases, and you should look at what matters most to you when you make your choice.&lt;/p&gt;

&lt;p&gt;Without further ado, let’s break down in detail how Python compares to Java.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Interpreted vs. compiled and dynamic vs. static
&lt;/h2&gt;

&lt;p&gt;The differences between Python and Java start at the most basic level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python is an interpreted language, while Java is a compiled language.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Interpreted languages convert human-readable code to machine-readable code on the go, as the program executes commands, making it easier to revise or debug.&lt;/p&gt;

&lt;p&gt;Conversely, compiled languages must translate source code into machine code before run time, making the code harder to revise or debug.&lt;/p&gt;

&lt;p&gt;What’s more, &lt;strong&gt;Python is dynamically typed, while Java is statically typed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even though code translation has nothing to do with type-checking, their definitions are mirror images of one another: dynamic typing means checking types during run time, while static typing means checking types before execution.&lt;/p&gt;

&lt;p&gt;The resulting difference is noticeable in compilation time. Generally speaking, we could say that &lt;strong&gt;Python launches faster and runs slower, while Java launches slower and runs faster.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s also a conflict between flexibility and reliability, respectively. Python and Java have opposing approaches to when errors are detected and how strict each language is about allowing variables to change types.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Entry point: Python gets you started faster
&lt;/h2&gt;

&lt;p&gt;One of my colleagues once said something that stuck with me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“You can learn the basics of Python over a weekend and start coding.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While slightly exaggerated, this statement isn’t far from the truth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python has a low entry point and is very user-friendly&lt;/strong&gt;, making it the perfect choice for junior developers and programming newcomers.&lt;/p&gt;

&lt;p&gt;Getting started on Python quickly is only one side of the coin, though; it takes much more time to learn how to use it well.&lt;/p&gt;

&lt;p&gt;Python can give you the same functionalities as Java, but only if your developers have more experience in it, which can be inconvenient in some cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Java, there is a definite learning curve and the entry point is high.&lt;/strong&gt; It takes a lot of time to start writing in it and get to know it well, and each API is a different story.&lt;/p&gt;

&lt;p&gt;However, once your developers put in the work, you will end up with higher-quality code from day one. So the time Java demands is well spent, but it will take a while before you see the results.&lt;/p&gt;

&lt;p&gt;In short, &lt;strong&gt;it takes weeks to get started on Python, and months to get started on Java.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Stability: Java is slightly more stable
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Java always requires more code.&lt;/strong&gt; The language is designed in such a way that everything needs to be defined from the get-go.&lt;/p&gt;

&lt;p&gt;This means you obviously need more time to review code written in Java, because there’s simply more of it—not to mention fixing all the potential issues you may find. When it’s bad enough, you’re actually better off rewriting the whole thing from scratch, rather than burning time and money to debug it all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But this code volume doesn’t necessarily have to be a bad thing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Certainly, the more code you have, the more complicated it gets—but if you write it well, you get more robust and stable software that crashes less. It may not matter as much for smaller-scale projects, but it’s a very different story for large ones that process a lot of data of all kinds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This perceived stability is the reason large companies see Java as a strong language&lt;/strong&gt; that gives them order and security. Big players like banks or fintech businesses usually don’t think twice before settling on Java due to its seemingly superior stability, without considering other options.&lt;/p&gt;

&lt;p&gt;While Java may have traditionally been the go-to language for corporations, we should ask ourselves: &lt;strong&gt;can we really say that Java is the enterprise solution?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not quite. Python is also well equipped to handle large-scale software products; otherwise, tech giants like Dropbox, Instagram, or Google wouldn’t have chosen it for their tech stack. Actually, there’s a &lt;a href="https://www.stxnext.com/stx-new-blog/web-app-speed-website-performance/"&gt;particularly strong case to be made for using Python in fintech.&lt;/a&gt; All in all, &lt;strong&gt;it would be inaccurate to say that Python gives you an unstable product.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So why the preconception that Java is better for corporations?&lt;/p&gt;

&lt;p&gt;Other than sheer code volume—which isn’t always an advantage in and of itself—&lt;strong&gt;Java is seen as enterprise-friendly because of the strong library support it enjoys.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Java offers plenty of libraries that help you perform various tasks common in enterprise applications. Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.drools.org/"&gt;Drools&lt;/a&gt; (a Business Rule Engine),&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://lucene.apache.org/"&gt;Lucene&lt;/a&gt; (a search engine),&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hadoop.apache.org/"&gt;Hadoop&lt;/a&gt; (a Big Data tool).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Libraries matter. It’s the same reason Python is AI/ML-friendly—more on that later.&lt;/p&gt;

&lt;p&gt;The bottom line is that performance is a sum total of a plethora of factors, mostly involving your code environment and external support. That being said, the stability scale is slightly tipped in Java’s favor.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Speed: Python is perfect for building an MVP fast
&lt;/h2&gt;

&lt;p&gt;Python is known for its speed and famously easy to write in, making development really fast. If you’re pressed for time and looking to meet a deadline, you should go with Python.&lt;/p&gt;

&lt;p&gt;Building an MVP with medium-quality code written in Python, then refactoring it later is a perfectly valid solution. Sometimes, you even start off by doing a mockup to see how your product is going to work before you decide on the actual language. Python is an ideal choice for that purpose.&lt;/p&gt;

&lt;p&gt;Time is decidedly in favor of Python. &lt;strong&gt;It can take months to build an MVP with Java, while with Python you can get to that stage in a matter of weeks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In line with this, Java projects usually take years—a year-long project is considered small—while for Python it is perfectly normal to have projects that require only months of work.&lt;/p&gt;

&lt;p&gt;What’s more, &lt;strong&gt;Java usually requires larger development teams. Python demands fewer developers,&lt;/strong&gt; and sometimes even one will suffice, helping you lower the total cost of your project.&lt;/p&gt;

&lt;p&gt;For all of these reasons, &lt;a href="https://www.stxnext.com/blog/why-python-should-be-the-programming-language-for-your-startup/"&gt;Python is a great choice for startups&lt;/a&gt;. If developing an MVP as fast as possible is your top priority, Python won’t let you down.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Resources: Java requires a larger investment than Python
&lt;/h2&gt;

&lt;p&gt;Another reason why Java is considered the language of corporations, is because development in it demands a large budget and a lot of time. It’s a sizable investment all around.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python is more cost-effective than Java, which is why small- and medium-sized projects prefer it.&lt;/strong&gt; For most use cases, it’s a perfect fit.&lt;/p&gt;

&lt;p&gt;Mind you, just because Java is more stable and expensive doesn’t mean Python is unreliable or a lower tier language. Far from it.&lt;/p&gt;

&lt;p&gt;Writing some projects in Java can be overkill—form over content, if you will—but large companies with resources to spare often choose it over other languages simply because it is the pricier solution, and thus better in their eyes.&lt;/p&gt;

&lt;p&gt;The logic there is debatable, but it’s not like those corporations suffer for it.&lt;/p&gt;

&lt;p&gt;If you have plenty of time and a generous budget at your disposal, there’s no reason not to go with Java. You will end up with a product of highly comparable quality to Python, though your development will be longer and slower.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Trending technologies: Python is the best choice for AI/ML
&lt;/h2&gt;

&lt;p&gt;There are no two ways about it: Python has no equal when it comes to &lt;a href="https://www.stxnext.com/stx-new-blog/new-technologies-stx-next/"&gt;trending technologies&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The easy architecture of Python makes it a perfect fit for &lt;a href="https://www.stxnext.com/stx-new-blog/will-artificial-intelligence-replace-developers/"&gt;artificial intelligence&lt;/a&gt;, while Python’s simplicity and clarity gives it the necessary edge over other languages to effectively design the complex internal logic of &lt;a href="https://www.stxnext.com/stx-new-blog/getting-started-machine-learning-python/"&gt;machine learning&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Writing either in Java would require much more code, slowing down development and losing focus of the task at hand in the process.&lt;/p&gt;

&lt;p&gt;But the main reason Python has been adopted as the go-to solution for trending technologies is the strong support it offers with its &lt;a href="https://www.stxnext.com/blog"&gt;wide variety of ready-made libraries&lt;/a&gt;. Whatever technical novelty you’re after, there’s a Python tool out there to help you out.&lt;/p&gt;

&lt;p&gt;The race for quicker implementation of AI or ML is only picking up speed, and there’s every indication that Python will not only stay in the leader’s seat, but also continue to become more popular and widely used.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Key takeaways
&lt;/h2&gt;

&lt;p&gt;If your top priority is development speed, go with Python; if your top priority is stability over all else, go with Java.&lt;/p&gt;

&lt;p&gt;Generally speaking, Java is better equipped to handle complex tasks. On the other hand, Python is clearer, easier, and simpler—to read, write, and modify.&lt;/p&gt;

&lt;p&gt;Keep in mind that this is an oversimplification. Your choice should always depend on your individual needs, your budget, and the type of project you have in the works.&lt;/p&gt;

&lt;p&gt;However, if the current trends continue and the language keeps growing in popularity, one thing is certain: Python is the future.&lt;/p&gt;

&lt;p&gt;Does that mean we will soon see a day when one language emerges victorious, and the other fades into obscurity?&lt;/p&gt;

&lt;p&gt;Unlikely.&lt;/p&gt;

&lt;p&gt;What’s far more likely is that the battle will carry on for years to come, like so many others of the same kind.&lt;/p&gt;

&lt;p&gt;It’s up to you to decide: which side are you on?&lt;/p&gt;

</description>
      <category>python</category>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>Python vs. JavaScript: Is It a Fair Comparison?</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sun, 15 May 2022 11:53:03 +0000</pubDate>
      <link>https://dev.to/stx-next/python-vs-javascript-is-it-a-fair-comparison-531a</link>
      <guid>https://dev.to/stx-next/python-vs-javascript-is-it-a-fair-comparison-531a</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Michał Słupski&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When we talk about building a project with Python or &lt;a href="https://www.stxnext.com/services/javascript-development/"&gt;JavaScript&lt;/a&gt;, we very rarely mean building every software component with one programming language.&lt;/p&gt;

&lt;p&gt;That’s just not how modern software development works. If you want to build software that’s up to standards, make it before the deadline, or create an app that will handle millions of users, you’re usually going to end up using several languages, frameworks, tools, and APIs.&lt;/p&gt;

&lt;p&gt;So if we want to compare Python vs. JavaScript, we should talk about &lt;strong&gt;building mission-critical components&lt;/strong&gt; of your software with either language.&lt;/p&gt;

&lt;p&gt;This is going to be our main theme for this article, and we’ll also talk about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;how Instagram became the biggest Python app in the world,&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;what are the most natural applications of Python and JavaScript,&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;how these two languages complement each other.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A quick introduction to Python and JavaScript
&lt;/h2&gt;

&lt;p&gt;Before we get into the nitty-gritty, let’s go over a few basic facts about Python and JavaScript. I won’t bore you with irrelevant details. This is just a rundown of how these languages came to fame, and what’s unique about their current position in the world of programming.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Python became one of the biggest programming languages
&lt;/h3&gt;

&lt;p&gt;Python first came out in 1991. It was built as a general-purpose programming language, so it can be used to solve any problem that can be quantified and described in code.&lt;/p&gt;

&lt;p&gt;The tech market has seen a big surge in Python’s popularity in recent years. It was already popular thanks to web development frameworks like &lt;a href="https://www.stxnext.com/blog/flask-vs-django-comparison/"&gt;Django&lt;/a&gt;, and because it was popular in the academic environment. Then it became the language of choice for &lt;a href="https://www.stxnext.com/blog/getting-started-machine-learning-python/"&gt;machine learning&lt;/a&gt; and data processing, which further increased Python’s popularity.&lt;/p&gt;

&lt;p&gt;Thanks to the web development framework Django, Python is also quite popular on the web—although not quite as popular as JavaScript. In the &lt;a href="https://insights.stackoverflow.com/survey/2020#most-popular-technologies"&gt;2020 StackOverflow developers survey&lt;/a&gt;, JavaScript holds the top position with 67.7% out of 65,000 developers using it. Python is used by 44.1%. In terms of frameworks, JavaScript libraries and frameworks jQuery, &lt;a href="https://www.stxnext.com/blog/react-vs-angular-comparison/"&gt;React and Angular&lt;/a&gt; hold the 3 top spots. Django comes up on the 10th spot.&lt;/p&gt;

&lt;p&gt;The cool thing about Python is that it’s used by many scientists and researchers. For people well-versed in the complexities of science, Python is an easy language to learn, even if they aren’t particularly tech-savvy. It’s very useful for fast prototyping, which makes it even more appealing for scientists.&lt;/p&gt;

&lt;p&gt;It’s all because Python is one of the simplest languages, but it’s a kind of easy-to-learn, hard-to-master sort of thing. Even if you’re not a programmer, but you want to automate a simple process—like scraping data from a website, or moving data from one program to another—it shouldn’t take you long to get Python to do the work for you.&lt;/p&gt;

&lt;p&gt;And if you put the time in and really master Python, you can use it to build a wide variety of software.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript’s long way to becoming a general programming language
&lt;/h3&gt;

&lt;p&gt;JavaScript first came out in 1995. Web apps weren’t a thing back then, and the goal of JavaScript was to make the web into a real application platform.&lt;/p&gt;

&lt;p&gt;JavaScript hasn’t had an easy life. It was hated by a lot of developers due to some of the design choices, as well as poor marketing, and it was limited technologically by low internet speed and low bandwidth. Plus, for a long time there was a problem with cross-browser compatibility, making it hard for developers to build sites that would work on all browsers.&lt;/p&gt;

&lt;p&gt;For several years, its popularity was growing at a pretty stable pace. One of the first libraries that removed the issue of cross-browser compatibility was jQuery, released in 2006. It made it easy to add interactivity to websites. The next major framework was AngularJS. It was later replaced by Angular 2+, which is still very popular in enterprise-scale solutions. &lt;/p&gt;

&lt;p&gt;Around 2011/2012 was the first time that JavaScript became supported by all major browsers at the time—Firefox, Chrome, Opera, and Safari. But even now, it’s still not 100% supported. That’s because JavaScript is regularly getting new features, so browser developers have to constantly work on improving JS support.&lt;/p&gt;

&lt;p&gt;In 2013, the Facebook engineering team released React, which quickly became popular, and played a big part in cementing JavaScript’s position as the web’s favorite workhorse.&lt;/p&gt;

&lt;p&gt;Of course, this is an extremely simplified version of JavaScript’s history; the real version is much longer, and more complex. The main point is that a lot of things had to happen in order to bring JavaScript to where it is now.&lt;/p&gt;

&lt;p&gt;At the moment, new versions of JavaScript are becoming more similar in design to a full-fledged general-purpose programming language.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use Python vs. JavaScript for mission-critical components
&lt;/h2&gt;

&lt;p&gt;When a mission-critical component or system breaks down for too long, your whole project goes belly-up. This is the part where choosing the right technology really matters.&lt;/p&gt;

&lt;p&gt;With low-priority systems, you can browse around, try different options, and optimize costs. When you try to do that with mission-critical systems, you might end up writing a death sentence for your project from the start.&lt;/p&gt;

&lt;p&gt;For example, when you’re managing a mature photo- and video-sharing application with &lt;a href="https://www.statista.com/statistics/325587/instagram-global-age-group/#:~:text=With%20over%201%20billion%20monthly,91%20million%20Instagram%20users%20each."&gt;over 1 billion users worldwide&lt;/a&gt;, the servers that process the incredibly large amounts of content are mission-critical. The app that I’m thinking of is of course Instagram, or &lt;a href="https://www.youtube.com/watch?v=2mevf60qm60"&gt;“the world’s largest Python site.”&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://instagram-engineering.com/static-analysis-at-scale-an-instagram-story-8f498ab71a0c"&gt;As one of Instagram’s engineers put it,&lt;/a&gt; “Instagram Server is entirely Python-powered.” The Instagram server application is a “monolith, one big codebase of several million lines and a few thousand Django endpoints.” Every single photo, video, and like goes through the most popular Python web framework Django, &lt;a href="https://www.youtube.com/watch?v=lx5WQjXLlq8"&gt;as another Instagram engineer mentioned in a presentation.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does Instagram use Python to manage mission-critical servers?
&lt;/h3&gt;

&lt;p&gt;Instagram uses a big chunk of servers at the massive Facebook-owned data centers. Engineers don’t just manage the looks of the app, how your feed works, or the content suggestion algorithms. They literally have to make sure that the CPUs of their servers don’t overheat.&lt;/p&gt;

&lt;p&gt;That’s an extremely difficult task. Why did they choose Python as the main language?&lt;/p&gt;

&lt;p&gt;The answer can be found on the &lt;a href="https://instagram-engineering.com/web-service-efficiency-at-instagram-with-python-4976d078e366"&gt;Instagram developer blog&lt;/a&gt;: “We initially chose to use Python because of its reputation for simplicity and practicality, which aligns well with our philosophy of ‘do the simple thing first.’ But simplicity can come with a tradeoff: efficiency.”&lt;/p&gt;

&lt;p&gt;Simplicity and practicality. &lt;a href="https://twitter.com/martinfowler?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor"&gt;Martin Fowler&lt;/a&gt;, a true software development guru with decades of experience, and author of several books, &lt;a href="https://en.wikiquote.org/wiki/Martin_Fowler"&gt;once wrote&lt;/a&gt;, “Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”&lt;/p&gt;

&lt;p&gt;Which means that even when your goal is to make sure that machines don’t overheat from serving billions of users everyday, you don’t achieve that goal by being a better machine whisperer. You do that by writing code that other developers can easily understand, so they can quickly debug it if necessary, or build on top of it without wondering if they’ll break the system.&lt;/p&gt;

&lt;p&gt;Python is perfect for this purpose, because of its readability, cleanliness, and ease of understanding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Instagram use JavaScript?
&lt;/h3&gt;

&lt;p&gt;Now we get to the interesting part. Even though Instagram engineers use Python for their whole server, Python isn’t responsible for how the interface looks. It stores and manages all the data, but the interface that you see on your smartphone is built with native programming languages, and a lot of help from JavaScript.&lt;/p&gt;

&lt;p&gt;The mobile interfaces are built in Swift (iOS) and Java (Android), but the popular mobile frontend JavaScript framework, React Native, also plays a big part. &lt;a href="https://instagram-engineering.com/react-native-at-instagram-dd828a9a90c7"&gt;Instagram engineers chose it because they wanted to have high developer velocity&lt;/a&gt;—which means they wanted to be able to add new features to both iOS and Android versions of their app as fast as possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.stxnext.com/blog/why-use-react-native-your-mobile-app/"&gt;React Native&lt;/a&gt; is exactly what they needed, because it allows engineers to use the same code to ship features to different systems. They can use JavaScript code to create native interface views on both systems. &lt;/p&gt;

&lt;p&gt;They could’ve used another approach, like building separate interfaces in Swift and Java. But they chose the middle option, and went for React Native. Maintaining interfaces in Swift and Java, with support from React Native, allows Instagram developers to optimize costs and development time, making their life easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python vs. JavaScript—which language has more uses?
&lt;/h2&gt;

&lt;p&gt;Instagram’s example is a good benchmark for the current web and mobile industry. Many popular apps have a similar structure—Python on the backend and JavaScript on the frontend.&lt;/p&gt;

&lt;p&gt;Even PayPal, which is completely different from Instagram, has a similar tech stack. In a very simplified statement, they use Python for managing data and JavaScript for their user interfaces.&lt;/p&gt;

&lt;p&gt;The statement is simplified because if you were to get into the specifics of how they use different programming languages and tools, you’d quickly get overwhelmed with the complexity. Plus, they’re not as keen as Instagram on sharing details about their stack with the whole world.&lt;/p&gt;

&lt;p&gt;One blog post I was able to find explains that &lt;a href="https://medium.com/@_ericelliott/companies-who-trust-node-js-4bfb8385ab84"&gt;PayPal engineers use Node.js for their middle-tier infrastructure, meaning web servers and their frontend&lt;/a&gt;, because it allows them to use only JavaScript to build their sites.&lt;/p&gt;

&lt;p&gt;But again, this isn’t mission-critical. The mission-critical parts of PayPal are hidden under all of that, a lot of it coded in Python (and most likely several other languages), and taking care of security, stability, and data management.&lt;/p&gt;

&lt;p&gt;JavaScript is not built for mission-critical systems. It started as a programming language for adding interactivity to websites, and even though it has grown into an incredibly useful tool, you could say it’s limited by design.&lt;/p&gt;

&lt;p&gt;On the other hand, Python was designed as a general-purpose programming language. It is used far beyond web development. It’s strongly rooted in the academic community. While it can be used to build a great website, with Python you can also &lt;a href="https://www.stxnext.com/blog/most-interesting-companies-using-python/"&gt;build neural networks for developing new drugs or AI technology that hides in the heart of apps like Uber.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, ultimately, Python has more uses than JavaScript. But there are several areas where JavaScript reigns supreme, so much so that it would be silly to try and use Python for them. &lt;/p&gt;

&lt;h2&gt;
  
  
  Where does JavaScript win with Python?
&lt;/h2&gt;

&lt;p&gt;JavaScript is a clear winner in the category of mobile development. There are some niche frameworks to do mobile development with Python—like &lt;a href="https://kivy.org/#home"&gt;Kivy&lt;/a&gt; and &lt;a href="https://riverbankcomputing.com/software/pyqt/intro"&gt;PyQT&lt;/a&gt;—but pretty much nobody uses them.&lt;/p&gt;

&lt;p&gt;It would make more sense for a Python developer to learn JavaScript and use its most popular mobile development framework, React Native, to build an app.&lt;/p&gt;

&lt;p&gt;Another area where JavaScript wins is frontend development. It has the best frameworks for building modern interfaces (React, Angular, Vue). With Node.js, developers can use JavaScript to also build the server side of their applications. Thanks to &lt;a href="https://jamstack.org/"&gt;JAMstack&lt;/a&gt; (JavaScript + APIs + markup), developers can build super-fast, beautiful web apps within very short deadlines.&lt;/p&gt;

&lt;p&gt;For a small/medium web and mobile development team on a budget and with tight deadlines, JavaScript is definitely the best option.&lt;/p&gt;

&lt;p&gt;And, as the Instagram and PayPal examples show, when you combine Python with JavaScript, you can build amazing applications that dominate markets and revolutionize life for billions of people.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is JavaScript better than Python in terms of performance?
&lt;/h2&gt;

&lt;p&gt;JavaScript was built to be fast on the web. When you compare a Node.js web app to a Python app, the Node.js one is almost definitely going to be faster.&lt;/p&gt;

&lt;p&gt;As &lt;a href="https://towardsdatascience.com/python-vs-node-js-which-one-is-best-for-your-project-e98f2c63f020"&gt;Towards Data Science&lt;/a&gt; puts it, “Python is comparatively slower in performance as it processes requests in a single flow, unlike Node.js, where advanced multithreading is possible.”&lt;/p&gt;

&lt;p&gt;There are ways to optimize Python’s performance by taking advantage of the fact that it uses the C programming language under the hood. For example, &lt;a href="https://numpy.org/"&gt;NumPy&lt;/a&gt; comes with optimized C code that makes Python code faster. &lt;a href="https://cython.org/"&gt;Cython&lt;/a&gt; is a compiler, and a superset of the Python language that enables developers to build fast C modules that speed up the execution of Python code.&lt;/p&gt;

&lt;p&gt;Generally speaking, JavaScript works well in I/O intensive situations—which means apps like Facebook, where a lot of data comes in and out of the application in real time, and it’s crucial that the user doesn’t have to wait for anything.&lt;/p&gt;

&lt;p&gt;Python works well in CPU-intensive situations—like a machine learning model that needs to crunch a huge amount of data to solve a specific problem. It’s also a good language for &lt;a href="https://developer.nvidia.com/how-to-cuda-python"&gt;doing heavy computations using GPUs.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then again, Instagram’s server is more of an I/O intensive situation, but it uses Python. It goes to show that if you know how to optimize Python, you can make it perform quickly.&lt;/p&gt;

&lt;p&gt;What about the &lt;strong&gt;other side of performance: time-to-market?&lt;/strong&gt; Both languages can be used to quickly build a simple MVP as long as it’s done by good developers. For complex programs, Python makes for a quicker time-to-market because it’s easy to read and easy to debug. Python fosters smooth collaboration. &lt;/p&gt;

&lt;p&gt;With JavaScript, things can get really complicated, really fast, which can lead to longer development times. For this reason a lot of companies have switched to TypeScript, which some developers would say is even easier to read and maintain than Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Machine learning with Python vs. JavaScript
&lt;/h2&gt;

&lt;p&gt;Python is the main language of choice for machine learning developers. It makes a lot of sense. Machine learning is complicated and involves huge amounts of data. Python is a simple and readable language, so it makes life easier for developers by removing complexity, and it has always been the standard for data science.&lt;/p&gt;

&lt;p&gt;The most popular ML frameworks—TensorFlow, scikit-learn, PyTorch—are mostly based on Python, and provide dedicated Python APIs which are the most popular way of using them. TensorFlow did release a JS version of the framework in 2018, and it allows developers to build machine learning models that work in the browser or in a Node.js server.&lt;/p&gt;

&lt;p&gt;But that’s not enough to win over the ML world. Python is perfectly suited for machine learning, and it’s unlikely to be supplanted by another language in the near future.&lt;/p&gt;

&lt;h2&gt;
  
  
  The future of Python and JavaScript
&lt;/h2&gt;

&lt;p&gt;Everything we talked about in this article leads to the conclusion that comparing Python and JavaScript isn’t really fair. These languages were designed with different goals in mind, which led to the differences in how they’re currently applied in software development.&lt;/p&gt;

&lt;p&gt;And it’s exactly those differences that allow these technologies to perfectly supplement each other in the modern world of programming.&lt;/p&gt;

&lt;p&gt;Will that change in the future? At the moment, JavaScript’s position as the most powerful web and mobile application development toolset seems very strong. More and more, it’s being turned into a general-purpose programming language, but it’s unclear if it could be a good substitute for a language like Python.&lt;/p&gt;

&lt;p&gt;As for Python, it’s most likely going to continue to dominate the machine learning market, as well as academia, because of Python’s readability and ease of use, as well as its power for manipulating data.&lt;/p&gt;

&lt;p&gt;In the end, the choice of your tech stack will always depend on the nature of your project, availability of programmers, and multiple other variables.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>python</category>
      <category>discuss</category>
    </item>
    <item>
      <title>DevOps: How to Host a Simple Static Website on AWS S3</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sat, 16 Apr 2022 14:03:43 +0000</pubDate>
      <link>https://dev.to/stx-next/devops-how-to-host-a-simple-static-website-on-aws-s3-3klf</link>
      <guid>https://dev.to/stx-next/devops-how-to-host-a-simple-static-website-on-aws-s3-3klf</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Adam Stempniak and Adrian Dratwicki&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’re thinking of hosting a website, you typically have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;buy a virtual server and manage it yourself,&lt;/li&gt;
&lt;li&gt;use the services of a hosting company.
The latter solution is one of the simplest and most popular when it comes to setting up websites, since it makes them easy to manage and cheap to maintain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using a hosting company usually comes down to getting access to an FTP server or panel, where you can upload the files necessary for your site to work. The rest is handled by your hosting service provider.&lt;/p&gt;

&lt;p&gt;But what if I told you there was a third way? An even better solution for static websites?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this article, I’ll show you how to host your website on AWS S3. I’ll also tell you how using AWS S3 benefitted one of our clients.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you host your static website on AWS S3?
&lt;/h2&gt;

&lt;p&gt;Not everyone knows Amazon S3 offers a functionality that allows you to host a static website—“static” being the key here. The website should be simple, without much happening on the backend, since server-side scripts like PHP, JSP, or ASP.NET are not supported.&lt;/p&gt;

&lt;p&gt;The best use case for this are company or personal sites serving as business cards, where your users will mostly find your contact information.&lt;/p&gt;

&lt;p&gt;However, if you’re in need of using a CMS like &lt;a href="https://wordpress.com/"&gt;Wordpress&lt;/a&gt;, I suggest you look at companies that provide hosting solutions or use a dedicated service like &lt;a href="https://aws.amazon.com/lightsail/"&gt;AWS Lightsail&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the benefits of using AWS S3 static website hosting?
&lt;/h2&gt;

&lt;p&gt;There are many reasons why you should host your website on AWS S3.&lt;/p&gt;

&lt;p&gt;Among others, it’s because the service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;manages everything, so there’s no need for you to worry about underlying software like the web server or the operating system in general;&lt;/li&gt;
&lt;li&gt;scales well for temporary high traffic load;&lt;/li&gt;
&lt;li&gt;is cheap (in the Frankfurt region, the cost is $0.00043 per 1,000 GET requests);&lt;/li&gt;
&lt;li&gt;has great integration with CloudFront;&lt;/li&gt;
&lt;li&gt;is simple to operate, allowing you to set up your website in a blink of an eye.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What do you need to host a static website on AWS S3?
&lt;/h2&gt;

&lt;p&gt;You need to meet certain requirements before hosting your website on S3.&lt;/p&gt;

&lt;p&gt;Make sure you have the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;registered domain (for the purposes of this article, let’s assume you own a domain named “example.com”);&lt;/li&gt;
&lt;li&gt;access to the panel that allows you to manage the DNS records for your domain;&lt;/li&gt;
&lt;li&gt;AWS account;&lt;/li&gt;
&lt;li&gt;basic knowledge of operating the S3 service;&lt;/li&gt;
&lt;li&gt;fully prepared website (I won’t be showing you how to build your own website in this article).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A 4-step guide to AWS S3 static website hosting
&lt;/h2&gt;

&lt;p&gt;I will now walk you through the process of hosting your site on S3.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Creating logging buckets
&lt;/h3&gt;

&lt;p&gt;Let’s start by creating a bucket in S3. It will log the requests to your website. This isn’t mandatory, but I think there’s always value in collecting such information.&lt;/p&gt;

&lt;p&gt;I suggest you call this bucket “example.com-logs.” Configure it by keeping the default settings for all the options, with the exception of “Manage system permissions.” Here, it’s necessary to grant write access to the S3 Log Delivery group.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kCXQpBhK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o9evd9zgiaxn5f3s4srh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kCXQpBhK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o9evd9zgiaxn5f3s4srh.png" alt="Granting write access to the S3 Log Delivery group" width="730" height="320"&gt;&lt;/a&gt;&lt;em&gt;Granting write access to the S3 Log Delivery group&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you intend to host more than one website on S3, you’ll be better off using a different, collective name for this bucket. Setting up the right prefixes will minimize the risk of you confusing logs from multiple sites—more on that later.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Creating S3 buckets
&lt;/h3&gt;

&lt;p&gt;Moving on, we’ll create 2 buckets in S3. We’ll put the files with your website’s code in one of them.&lt;/p&gt;

&lt;p&gt;Your buckets should be named after your domain, so call the 1st one “example.com” and the other one “www.example.com.”&lt;/p&gt;

&lt;p&gt;Let’s focus on the 1st bucket now.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f0qGZF4w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xt2yllsxxeohw8prbcs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f0qGZF4w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xt2yllsxxeohw8prbcs.png" alt="Creating a bucket for your website" width="730" height="320"&gt;&lt;/a&gt;&lt;em&gt;Creating a bucket for your website&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When configuring your bucket, I recommend turning on object versioning. It may be useful in case you wish to restore a previous version of an image or an entire website template.&lt;/p&gt;

&lt;p&gt;The next move is turning on request logging to your site. Select the bucket you’ve created as the &lt;strong&gt;target bucket&lt;/strong&gt;. The folder where the logs are placed will be the prefix.&lt;/p&gt;

&lt;p&gt;If you’re going to be collecting logs from several buckets to this one, I suggest you set the domain name as the prefix. Thanks to this, you’ll know which bucket the logs originate from as you browse through them.&lt;/p&gt;

&lt;p&gt;Right now, we’ll just use the &lt;strong&gt;logs&lt;/strong&gt;, since we’re hosting only 1 site.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1t0s8iWI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/na284uik78n1ohthl2yh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1t0s8iWI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/na284uik78n1ohthl2yh.png" alt="Bucket configuration" width="730" height="320"&gt;&lt;/a&gt;&lt;em&gt;Bucket configuration&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The next step is unlocking public ACLs for objects.&lt;/p&gt;

&lt;p&gt;Doing so is crucial, otherwise you won’t be able to publicly share the objects. As a result, displaying your website in the browser will be impossible.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P-iOAMU9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8un616zt7oq5yfjxsm2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P-iOAMU9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8un616zt7oq5yfjxsm2.png" alt="Unlocking public ACLs" width="730" height="320"&gt;&lt;/a&gt;&lt;em&gt;Unlocking public ACLs&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Your 1st bucket is almost ready. Now you can upload the files with your site’s code to it.&lt;/p&gt;

&lt;p&gt;As you upload the files, remember to make sure that they’re publicly accessible.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hzThkXUl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8vyyhjapoebblksl6543.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hzThkXUl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8vyyhjapoebblksl6543.png" alt="Granting public access to bucket objects" width="730" height="320"&gt;&lt;/a&gt;&lt;em&gt;Granting public access to bucket objects&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the following step, you have the option to choose the Storage class. Leave it set to “standard.”&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Enabling static website hosting
&lt;/h3&gt;

&lt;p&gt;It’s time to enable the hosting service.&lt;/p&gt;

&lt;p&gt;Go to your bucket’s Properties. You’ll find the “Static website hosting” tab there.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EfTWm5Ro--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/589zum19nkds2j7u0f10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EfTWm5Ro--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/589zum19nkds2j7u0f10.png" alt="Bucket properties view" width="730" height="320"&gt;&lt;/a&gt;&lt;em&gt;Bucket properties view&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By default, the service will be disabled. Enable it.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8C0rCvtC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b7yd83re0squ6wa0ev3j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8C0rCvtC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b7yd83re0squ6wa0ev3j.png" alt="Enabling static website hosting" width="730" height="320"&gt;&lt;/a&gt;&lt;em&gt;Enabling static website hosting&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You need to input the name of your website’s “core” file. Usually, it’s “index.html,” as is the case here.&lt;/p&gt;

&lt;p&gt;If you have a file that should be displayed in the event of an error, it should also be defined here—and placed in your bucket beforehand, naturally. However, this only applies to errors belonging to the 4XX group.&lt;/p&gt;

&lt;p&gt;Additionally, it’s worth it to save the endpoint displayed above at this point.&lt;/p&gt;

&lt;p&gt;If you’ve done all of that correctly, your website should display as intended once you enter the &lt;strong&gt;endpoint&lt;/strong&gt; into the browser.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vbbUeTuP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d2dw6bd3adwn366hu4lp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vbbUeTuP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d2dw6bd3adwn366hu4lp.png" alt="Checking if our site is accessible" width="730" height="320"&gt;&lt;/a&gt;&lt;em&gt;Checking if our site is accessible&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s create the 2nd bucket now: “www.example.com.”&lt;/p&gt;

&lt;p&gt;You can leave the entire configuration set to default. What you care about the most here is redirection from “www.example.com” to “example.com.”&lt;/p&gt;

&lt;p&gt;Once you create this bucket, go to its Properties and enable Static website hosting, just like before. This time around, though, you should also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pick “Redirect requests” from the available options,&lt;/li&gt;
&lt;li&gt;input the “example.com” domain in the “Target bucket or domain” field,&lt;/li&gt;
&lt;li&gt;set “http” as the protocol.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r3S9efJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8mhuvmtmiw12tjul3ib5.png" alt="Setting up redirection for ''www.example.com''" width="730" height="320"&gt;&lt;em&gt;Setting up redirection for ''&lt;a href="http://www.example.com'"&gt;www.example.com'&lt;/a&gt;'&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Setting up DNS records
&lt;/h3&gt;

&lt;p&gt;Your website should now be online. However, it’s clear you don’t want to use this lengthy URL as the access point to the site.&lt;/p&gt;

&lt;p&gt;In order to use the “example.com” domain, log into the panel where you can add new DNS records. In this instance, I use Cloudflare to manage DNS records, but regardless, what you need to do comes down to 2 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Removing existing records that point “example.com” and “www.example.com” to an IP address or other domains&lt;/li&gt;
&lt;li&gt;Adding 2 &lt;strong&gt;CNAME&lt;/strong&gt; records&lt;/li&gt;
&lt;li&gt;“example.com” that will point to our “example.com” bucket endpoint&lt;/li&gt;
&lt;li&gt;“www.example.com” that will point to our “www.example.com” bucket endpoint
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---g7MaDqr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zswta0bz1ymzuyudpe1b.png" alt="DNS records settings for our website" width="730" height="320"&gt;&lt;em&gt;DNS records settings for our website&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should wait a while for the DNS records to propagate. After that, you’ll be able to enter your website from either the “example.com” or “www.example.com” domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  How one of our clients benefitted from AWS S3
&lt;/h2&gt;

&lt;p&gt;At STX Next, we often use Amazon S3 in our projects for storing static or media files uploaded by the user and generated by the application. Static files are files such as images or CSS/JS files that aren’t generated on the go.&lt;/p&gt;

&lt;p&gt;Very often, &lt;strong&gt;this is highly sensitive data&lt;/strong&gt;, like PDFs containing confidential user information. Because S3 supports server/client-side encryption, the service is &lt;strong&gt;a really safe solution&lt;/strong&gt; to store this kind of data.&lt;/p&gt;

&lt;p&gt;One of our clients came to us with the intention of moving his entire infrastructure from a different hosting provider to AWS. The client had only one virtual server, where multiple services were installed.&lt;/p&gt;

&lt;p&gt;One of these services was NGINX, which distributed the traffic between the application and the main company website. The client’s main site consisted only of some HTML, CSS, and JS files.&lt;/p&gt;

&lt;p&gt;Through this website, a potential buyer could find the client’s contact information and learn about their services. In the process of moving the infrastructure to AWS, we decided to separate this website from the application services and move the database to the RDS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It was the most convenient and secure choice. One instance, one role.&lt;/strong&gt; If we ever have to move the application to another instance, we won’t have to concern ourselves with additional components like website, database, etc.&lt;/p&gt;

&lt;p&gt;To spin up a new instance, we’ll only have to run the script that will automatically install packages required for the application to start running, then simply deploy it to the server. That’s it.&lt;/p&gt;

&lt;p&gt;Maintaining an additional EC2 instance for a single website is unnecessary and we don’t expect any heavy traffic to the main website—but if it happens, the AWS will handle it.&lt;/p&gt;

&lt;p&gt;As you can see, static website hosting on S3 turned out to be the perfect solution for us, and I believe the same will be true for your business.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;You now know how to create 2 S3 buckets for your website. The 1st bucket you’ve created allows you to store files required to run your website, while the 2nd one serves strictly redirection purposes.&lt;/p&gt;

&lt;p&gt;You’ve set up DNS records, so that your visitors can now enter your website through a friendly domain. Your site is available to the world, and you don’t have to worry about underlying servers, software updates, scaling, or costs.&lt;/p&gt;

&lt;p&gt;If you’d like to use the HTTPS protocol—which is highly recommended—you should take a look at the &lt;a href="https://aws.amazon.com/cloudfront/"&gt;CloudFront&lt;/a&gt; service. Using Cloudflare gives you the ability to establish a SSL/TLS connection by routing traffic through their servers. However, the traffic is encrypted between the client and the Cloudflare servers. For the full SSL/TLS setup, CloudFront is required.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>AWS Glue Studio Guide—How to Build Data Pipelines Without Writing Code</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Mon, 11 Apr 2022 07:34:37 +0000</pubDate>
      <link>https://dev.to/stx-next/aws-glue-studio-guide-how-to-build-data-pipelines-without-writing-code-4ffm</link>
      <guid>https://dev.to/stx-next/aws-glue-studio-guide-how-to-build-data-pipelines-without-writing-code-4ffm</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Maksymilian Jaworski and Lidia Kurasińska&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You’ve probably heard that creating ETL (extract, transform, load) pipelines, especially complex ones, is a complicated task. Various tools have been developed to make this process much easier, but most of them still require some knowledge of a programming language (for example, &lt;a href="https://www.stxnext.com/blog/r-and-python-comparison/"&gt;Python or R&lt;/a&gt;) often combined with an understanding of tools such as Spark.&lt;/p&gt;

&lt;p&gt;In August 2017, AWS created Glue DataBrew, a tool perfect for data and business analysts, since it facilitates data preparation and profiling. A year ago, the company released AWS Glue Studio, a visual tool to create, run, and monitor Glue ETL Jobs.&lt;/p&gt;

&lt;p&gt;AWS Glue Studio supports various types of data sources, such as S3, Glue Data Catalog, Amazon Redshift, RDS, MySQL, PostgreSQL, or even streaming services, including Kinesis and Kafka. Out of the box, it offers many transformations, for instance ApplyMapping, SelectFields, DropFields, Filter, FillMissingValues, SparkSQL, among many. We can save the results of our jobs to Amazon S3 and tables defined in the &lt;strong&gt;AWS Glue Data&lt;/strong&gt; Catalog.&lt;/p&gt;

&lt;p&gt;Also, apparently, we can use it all without knowing Spark, as Glue Studio will generate Apache Spark code for us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, let’s see in practice what we can do with AWS Glue Studio. I promised myself that I would try not to write a single line of code when solving my case.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, I used a slightly modified &lt;a href="https://archive.ics.uci.edu/ml/datasets/online+retail"&gt;E-Commerce Data&lt;/a&gt; dataset.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS Glue Studio in practice
&lt;/h2&gt;

&lt;p&gt;Let’s assume that you received the following task from your data analysts:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;One system is uploading daily CSV files, which contain the following information: invoice_no, stock_code, description, quantity, unit_price, customer_id, country, invoice_date. Calculate the total number of sold items (count quantity) and the total purchase value (sum per item quantity multiplied by unit_price) per customer and day. Save the results in a CSV file separated by commas in an S3 bucket.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I know this sounds more like a job for a data analyst and some of you probably think this is a simple and boring task, but don’t worry, we will add some action later on.&lt;/p&gt;

&lt;p&gt;My input files are located in this directory: aws-glue-demo-202109/inputs&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOo7ddQR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpk8yvoet4x8zok03yjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOo7ddQR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpk8yvoet4x8zok03yjg.png" alt="S3 Input files" width="880" height="158"&gt;&lt;/a&gt;Okay, let’s see how we can do this with AWS Glue Studio.&lt;/p&gt;

&lt;p&gt;To access it, choose AWS Glue from the main AWS Management Console, then from the left panel (under ETL) click on AWS Glue Studio. Go to Jobs, and at the top you should see the Create job panel—it allows you to create new jobs in a few different ways: &lt;em&gt;Visual with a source and target, Visual with a blank canvas, Spark script editor,&lt;/em&gt; and &lt;em&gt;Python Shell script editor&lt;/em&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NKuL_eQ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jcvi7hy90jp0skoreh82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NKuL_eQ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jcvi7hy90jp0skoreh82.png" alt="Create job section of AWS Glue Studio" width="880" height="239"&gt;&lt;/a&gt;I selected Visual with a blank canvas. It should create a new, empty, untitled job.&lt;/p&gt;

&lt;p&gt;Before we start building our ETL process, let’s go to the Job Details tab and discuss some important properties that determine how AWS Glue will run the job. Except for the job’s name, you can change those settings any time you want.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y7lsE8BC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkhhz5zhndpqwn5xcgw3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y7lsE8BC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkhhz5zhndpqwn5xcgw3.png" alt="Create job details in AWS Glue Studio" width="405" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Glue version&lt;/em&gt;—it determines the versions of Apache Spark and Python that are available to the job. Note: some features might not be available for particular versions. For instance, at the time of writing, the Data Preview function is not working with 3.0, the latest version.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Language&lt;/em&gt;—either Python or Scala. I will go with Python.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Worker type&lt;/em&gt; (G.1X or G.2X)—for the G.1X worker type, each worker maps to 1 DPU. For the G.2X, it’s 2 DPU for each worker. I chose G.1X as it has way more resources than I will actually need.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Job bookmark&lt;/em&gt; (Enable, Disable, Pause)—now &lt;strong&gt;this is a pretty important variable&lt;/strong&gt;, especially that Enable is a default value. In a nutshell: when you enable job bookmarks, once you process some data (e.g., an S3 file), &lt;strong&gt;the data is marked by a job as processed and will not be processed by this job in the next executions.&lt;/strong&gt; Bookmarks are tied to jobs, so different jobs can process the same file. I’m disabling it now, as I will probably have to process the same files over and over again during the development of my job. For extended description of Job Bookmarks, please read &lt;a href="https://docs.aws.amazon.com/glue/latest/dg/monitor-continuations.html?icmpid=docs_glue_studio_helppanel"&gt;Tracking Processed Data Using Job Bookmarks.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Number of retries&lt;/em&gt;—this is pretty self-explanatory. I switch this value from 3 to 0 right now, as I don’t want Glue to retry executing a task which fails just because I made some dummy mistake, like using an empty file, for example.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m not going into the &lt;em&gt;Advanced properties&lt;/em&gt; section, but keep in mind that this is where you can configure your S3 script path, Spark UI logs path, set maximum concurrency, disable metrics, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; you have to set those settings for each created job, unless you’re cloning a job—then its copy has the same settings as the original one.&lt;/p&gt;

&lt;p&gt;Now, let’s go back to the Visual section.&lt;/p&gt;

&lt;p&gt;1.From Source, select the Amazon S3 node.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--049JBelT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atqa2f8t9txf5qcw3o3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--049JBelT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atqa2f8t9txf5qcw3o3s.png" alt="AWS Glue Studio - source types - Amazon S3 node" width="692" height="625"&gt;&lt;/a&gt;In Data source properties - S3 set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3 source type: S3 location—so you will access S3 files directly&lt;/li&gt;
&lt;li&gt;S3 url: s3://aws-glue-demo-202109/input/&lt;/li&gt;
&lt;li&gt;Recursive: true&lt;/li&gt;
&lt;li&gt;Data format: CSV&lt;/li&gt;
&lt;li&gt;Delimiter: Comma (,)
&lt;strong&gt;Note:&lt;/strong&gt; you are limited to the following delimiters: Comma, Ctrl+A, Pipe, Semicolon, Tab.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4D97F9rl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gx9k24tjur6tjeqf68e6.png" alt="AWS Glue Studio - data source properties" width="880" height="478"&gt;Now, let’s go to the Output schema tab.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6alQfTcO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9pl2tw4mtg2k3hkdgpp2.png" alt="AWS Glue Studio - data output schema" width="693" height="449"&gt;Well, those datatypes don’t look right—you will have to change this. Click the &lt;em&gt;Edit&lt;/em&gt; button and for each key set the right data type (according to the information provided by data analysts): 
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZK-Lk6P1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kumvr8pwctqyrb1g3fqe.png" alt="Output schema tab" width="695" height="395"&gt;It looks good, click on Next and go to the next step.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2.Doing aggregations. Here lies the first “obstacle,” as Glue Studio does not have a built-in transformation node which allows us to do aggregates. The best solution is to use &lt;em&gt;Transform - Spark SQL node&lt;/em&gt;. You can name the node &lt;em&gt;aggByCustomerByDate&lt;/em&gt;, and in the &lt;em&gt;transform&lt;/em&gt; section, select &lt;em&gt;Amazon S3&lt;/em&gt; (the name of the parent node) as input source and give it a sales alias, which you can use in your SQL code as the table name. In the &lt;em&gt;Code block&lt;/em&gt;, you can put a simple SQL query, which takes the &lt;em&gt;customer_id&lt;/em&gt; column, gets the date from the &lt;em&gt;invoice_date&lt;/em&gt; column, sums &lt;em&gt;quantity&lt;/em&gt; and &lt;em&gt;quantity*unit_price&lt;/em&gt;, and groups it by customer and &lt;em&gt;sale_date&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let’s assume that it doesn’t break my “not-writing-a-line-of-code” rule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; this editor does not verify syntax, so double-check your query before you run it.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qfbVfyoB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxaxicz4m4q70hjc9i6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qfbVfyoB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxaxicz4m4q70hjc9i6o.png" alt="AWS Glue Studio - transform node" width="880" height="266"&gt;&lt;/a&gt;3.Now that you are done with aggregates, save its result to S3. From the &lt;em&gt;Target&lt;/em&gt; menu, choose Amazon S3, pick up CSV Format. Decide if you want to apply any compression and set the target location to &lt;em&gt;s3://aws-glue-demo-202109/output/1st-direct&lt;/em&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y4tWpnhb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gdt6jia5qzl9osdyr3x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y4tWpnhb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gdt6jia5qzl9osdyr3x.png" alt="AWS Glue Studio - target node properties" width="880" height="338"&gt;&lt;/a&gt;4.The job is ready. In the right-upper corner, hit Save, then Run, and wait. You can go into the Runs tab and see the job progress, as well as links to logs and run metadata.&lt;/p&gt;

&lt;p&gt;After a minute, you can see that the job has succeeded.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b_m8-pQ7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gljyvl30bvycumqdz145.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b_m8-pQ7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gljyvl30bvycumqdz145.png" alt="AWS Glue Studio - job run finished" width="880" height="315"&gt;&lt;/a&gt;Now, go to the target S3 directory. You have 4 files here:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bn-AGUW0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k05k94wqdnfral0ahssv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bn-AGUW0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k05k94wqdnfral0ahssv.png" alt="AWS Glue Studio - target S3 directory" width="880" height="129"&gt;&lt;/a&gt;Each file contains &lt;em&gt;customer_id, sale_date, total_quantity&lt;/em&gt; and &lt;em&gt;total_sale&lt;/em&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NEdtIAkT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8wo40euv60nhswo2p51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NEdtIAkT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8wo40euv60nhswo2p51.png" alt="Each file contains customer_id, sale_date, total_quantity and total_sale." width="469" height="92"&gt;&lt;/a&gt;Okay, that was quite quick and simple. But I’m not satisfied with this solution, and you might not be, either. True, I did calculations for all files, but what will happen tomorrow when the new file arrives? Like you, I don’t want to process all the data once again. We’re only interested in processing newly created files.&lt;/p&gt;

&lt;p&gt;Besides, data analysts also have some further requests.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;They remembered that sometimes quantity might be a negative value which indicates that an item was returned. They would like me to exclude those rows from the aggregations and store the list of returned items in a separate file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you took a good look at the last image, you should notice that the second row is missing a value for &lt;em&gt;customer_id&lt;/em&gt;. Analysts would like to get rid of empty customers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Analysts would like to link some customers’ data (first name, last name, address) to the file with aggregations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Working on four separate files is a bit troubling—they would prefer to have one file only.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s address my issue first. The way I see it, there are two possible approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The aforementioned Job Bookmarks. As the doc says: &lt;em&gt;“Job bookmarks are used to track the source data that has already been processed, preventing the reprocessing of old data. Job bookmarks can be used with JDBC data sources and some Amazon Simple Storage Service (Amazon S3) sources. Job bookmarks are tied to jobs. If you delete a job, then its job bookmark is also deleted. You can rewind your job bookmarks for your Glue Spark ETL jobs to any previous job run, which allows your job to reprocess the data. If you want to reprocess all the data using the same job, you can reset the job bookmark.”&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manually, or by using a function or some parameter, decide which files (day or range of days) should be processed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first solution seems really cool, but let’s say that I’m not 100% sure how the data is loaded—perhaps files are overwritten every day? Or they could suddenly start doing that? Or you’re going to modify our jobs often and re-run them for particular files, and you don’t want to remember about resetting the job bookmark?&lt;/p&gt;

&lt;p&gt;Either way, let’s say that for the sake of this article, you simply can’t or don’t want to rely on job bookmarks. What can you do now?&lt;/p&gt;

&lt;p&gt;You could filter out the data in, for instance, &lt;em&gt;Transform - Spark SQL node&lt;/em&gt;, but it doesn’t really solve the issue—the job will still be processing all files, you will just filter out the output or the data which goes into aggregations. You have to figure out how to divide those files “logically.”&lt;/p&gt;

&lt;p&gt;Instead of working directly with S3 files, try to organize S3 files into databases and tables. Perhaps then you will be able to query the data more efficiently. Use the AWS Glue Crawler for this.&lt;/p&gt;

&lt;p&gt;In a nutshell, AWS Glue can combine S3 files into tables that can be partitioned based on their paths. For example, if your files are organized as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bucket1/year/month/day/file.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then AWS Glue can create one table from all files in bucket1, which will be partitioned by year, month, and day. The level of partition creation is also definable, and you can have, for example, a table for each separate day, month or year. You’ll find more details &lt;a href="https://aws.amazon.com/blogs/big-data/work-with-partitioned-data-in-aws-glue/"&gt;in this article&lt;/a&gt; on working with partitioned data in AWS Glue.&lt;/p&gt;

&lt;p&gt;For now, there are two ideas for you to test:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a separate table for each day.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create one table with partitions by year, month, and day.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But before you create databases and tables, you have to reorganize the structure of your S3 bucket from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bucket/YYYYMMDD_data.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bucket/year/month/day/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws-glue-demo-2021/inputs/20210901_data.csv
aws-glue-demo-2021/inputs/20210902_data.csv
aws-glue-demo-2021/inputs/20210903_data.csv
aws-glue-demo-2021/inputs/20210904_data.csv
aws-glue-demo-2021/inputs/20210905_data.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;your files will be organized this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws-glue-demo-2021/inputs/2021/09/01/data.csv
aws-glue-demo-2021/inputs/2021/09/02/data.csv
aws-glue-demo-2021/inputs/2021/09/03/data.csv
aws-glue-demo-2021/inputs/2021/09/04/data.csv
aws-glue-demo-2021/inputs/2021/09/05/data.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once it’s done, you can start working with AWS Glue Crawler (which is also available from the AWS Glue Studio panel in the Glue Console tab.)&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kAOPUmGh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6s4xelwoe3n21kgephj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kAOPUmGh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6s4xelwoe3n21kgephj.png" alt="AWS Glue Studio - access Glue crawlers" width="241" height="246"&gt;&lt;/a&gt;First, configure a crawler which will create a &lt;strong&gt;single&lt;/strong&gt; table out of all the files.&lt;/p&gt;

&lt;p&gt;Click on &lt;em&gt;Add Crawler&lt;/em&gt;, then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Name the Crawler &lt;em&gt;get-sales-data-partitioned&lt;/em&gt;, and click &lt;em&gt;Next&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Keep the Crawler source type on default settings (Crawler source type: &lt;em&gt;Data stores &amp;amp; Crawl all folders&lt;/em&gt;), then click &lt;em&gt;Next&lt;/em&gt; again.&lt;/li&gt;
&lt;li&gt;Select S3 as the datastore and specify the path of &lt;em&gt;s3://aws-glue-demo-202109/inputs&lt;/em&gt; and click &lt;em&gt;Next&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;No, you don’t want to add another data store.&lt;/li&gt;
&lt;li&gt;Now, you can either choose an existing role or create a new one. Go ahead and create a new one.&lt;/li&gt;
&lt;li&gt;For now, choose &lt;em&gt;Frequency: Run on demand&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;To store the Crawler output, create a database called &lt;em&gt;sales_partitioned&lt;/em&gt; and select the created database from the drop-down menu. In configuration options, select &lt;em&gt;Ignore the change and don’t update the table in the data catalog and Delete tables and partitions from the data catalog&lt;/em&gt; (I will explain why later on), and click &lt;em&gt;Next&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Review your crawler and confirm.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--45WRA8no--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zylhnaqttp10zfqnobnn.png" alt="AWS Glue Studio - crawler creation setup" width="167" height="373"&gt;For the crawler that will create separate tables the process is pretty much the same; the only changes are in following steps:&lt;/li&gt;
&lt;li&gt;Step #1: Name it &lt;em&gt;get-sales-data-partitioned-sep&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Step #2: Choose an already existing role (created for the previous crawler.)&lt;/li&gt;
&lt;li&gt;Step #7: In Configure the crawler output, create a new database called &lt;em&gt;sales_partitioned_sep&lt;/em&gt;. In Group behavior for S3 - Table level, enter 5. Why 5? Well, counting from the beginning: bucket is the first level, inputs—the second one, year—the third one, month—the fourth one, and day comes fifth.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_7XfEo3J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/acb25dh4jabx3q4tld30.png" alt="AWS Glue Studio - crawler create database" width="680" height="437"&gt;Next, review your crawler and save it. At this point, you should have two crawlers that will create two separate databases—run both and wait.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After a while, you can see that the get-sales-data-partitioned crawler created one table and get-sales-data-partitioned-sep created nine tables.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4KvdS2eU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g4lapx03j4hirdplmohy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4KvdS2eU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g4lapx03j4hirdplmohy.png" alt="AWS Glue Studio - glue crawlers" width="880" height="261"&gt;&lt;/a&gt;Why nine? Most likely because someone created new files in the meantime. You can find out by going into &lt;em&gt;Databases&lt;/em&gt;, where you should see your databases:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VtD2BCiD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dn8mieh90gqat96324bj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VtD2BCiD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dn8mieh90gqat96324bj.png" alt="AWS Glue Studio - all databases catalog" width="413" height="187"&gt;&lt;/a&gt; In &lt;em&gt;sales_partitioned&lt;/em&gt; you should see one table:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1rSnndbY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wpwiqshsd0k2i6jlcgo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1rSnndbY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wpwiqshsd0k2i6jlcgo.png" alt="sales_partitioned catalog" width="880" height="85"&gt;&lt;/a&gt;Whereas in sales_partitioned_sep, you should see nine tables.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HTXtgKI0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qfykh8cksr3o9micij4o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HTXtgKI0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qfykh8cksr3o9micij4o.png" alt="Sales_partitioned_sep catalog" width="880" height="324"&gt;&lt;/a&gt;The first thing that stands out is that one of the tables repeated in two months got an ugly suffix. But let’s go to the input_partitioned table. At the bottom you should see columns, which are your partitions:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0flSzrwl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4uvz7upus6mzsnadmke.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0flSzrwl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4uvz7upus6mzsnadmke.png" alt="Edit schema" width="880" height="324"&gt;&lt;/a&gt;How to figure out what’s behind &lt;em&gt;partition_0, partition_1,&lt;/em&gt; and &lt;em&gt;partition_2&lt;/em&gt;? Click on &lt;em&gt;View Partitions&lt;/em&gt;: you can see that &lt;em&gt;partition_0&lt;/em&gt; is year, &lt;em&gt;partition_1&lt;/em&gt; is month, and &lt;em&gt;partition_2&lt;/em&gt; is day.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mPRrwcpG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0h5spuxtcmji77amubcr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mPRrwcpG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0h5spuxtcmji77amubcr.png" alt="Image description" width="880" height="249"&gt;&lt;/a&gt;Click on &lt;em&gt;Close Partitions&lt;/em&gt;, next &lt;em&gt;Edit Schema&lt;/em&gt;, and rename these columns. Save it, and now your table should look like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H5pc6fA6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ctqaxx23h3dai4dug6yf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H5pc6fA6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ctqaxx23h3dai4dug6yf.png" alt="Image description" width="880" height="328"&gt;&lt;/a&gt;&lt;strong&gt;Note:&lt;/strong&gt; now it is important to explain why I previously checked Ignore the change and don’t update the table in the data catalog option during crawler creation. If I had not selected this option and run the crawler tomorrow, the column names I gave (year, month, day) would have been overwritten back to partition_0, partition_1, and partition_2.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update! There is one thing that I missed while writing this article. If you name your S3 partitions the following way:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;year=2021/month=08/day=30/data.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Glue Crawler will automatically pick up partition names, and you won't have to rename columns by yourself.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now, back to your jobs—what are the options? On the left-hand side, you can see that I can select individual tables from the sales_partitioned_sep database. On the right-hand side, I have only one table to choose from, but I can send &lt;strong&gt;partition predicates.&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wNG-rnYc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67c4lkpl6qpjjlmols0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wNG-rnYc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67c4lkpl6qpjjlmols0v.png" alt="Partition predictates" width="880" height="299"&gt;&lt;/a&gt;Both approaches reduce the amount of initial data. However, there are few things that I don’t like about the second one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the names of the tables do not clearly indicate (at least in my case) what data we are working on,&lt;/li&gt;
&lt;li&gt;when I have to work on more than one day, I will have to add separate source nodes and create joins, whereas in the first solution, I will only have to modify the query in predicament pushdown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, so I’m good with the first one but, before we proceed, here are a few notes.&lt;/p&gt;

&lt;p&gt;Now that we are working with a &lt;em&gt;Data Catalog&lt;/em&gt; table instead of S3 files directly, we should note that the output of the file has changed. We no longer have &lt;em&gt;choice&lt;/em&gt; fields—now data types were defined by Glue Crawler.&lt;/p&gt;

&lt;p&gt;So, how can you change this? There are three options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you can edit schema types in the &lt;em&gt;Glue Data Catalog&lt;/em&gt; (same way we changed the partition name),&lt;/li&gt;
&lt;li&gt;you can change the types in the first step (like in the previous job),&lt;/li&gt;
&lt;li&gt;you can add a separate transformation node that will change the types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I chose the third option. Why? Firstly, because I want everyone to see that this step is taking place (that we are expecting some data types.) Secondly, because I want to show you another transformation.&lt;/p&gt;

&lt;p&gt;So, with partition predicate and extra step for applying data types, our job looks like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8uWbAUYG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b09eimn2hl3hm4nvseas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8uWbAUYG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b09eimn2hl3hm4nvseas.png" alt="Apply mapping" width="825" height="558"&gt;&lt;/a&gt;Now, back to the analyst issues.&lt;/p&gt;

&lt;p&gt;Firstly, let’s address item returns. You want to filter out rows with negative &lt;em&gt;unit_price&lt;/em&gt; and save them in a separate file. Add two additional transforms - &lt;em&gt;Filter nodes&lt;/em&gt; after &lt;em&gt;setDatatypes&lt;/em&gt; node. The first one (&lt;em&gt;getSales&lt;/em&gt;) takes records with &lt;em&gt;unit_price&lt;/em&gt; &amp;gt;= 0; the second one (&lt;em&gt;getReturns&lt;/em&gt;) takes records with &lt;em&gt;unit_price&lt;/em&gt; &amp;lt; 0. After &lt;em&gt;getSales&lt;/em&gt;, proceed with aggregations and then save it to S3; after &lt;em&gt;getReturns&lt;/em&gt;, just save it to S3.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xHGJTt5z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/euh240lesap9y7ozbmsz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xHGJTt5z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/euh240lesap9y7ozbmsz.png" alt="Image description" width="880" height="506"&gt;&lt;/a&gt;&lt;strong&gt;Note:&lt;/strong&gt; it seems that you cannot combine or and and operators in one step. If you really need to do it, you should use a Spark SQL node and write a custom SQL query.&lt;/p&gt;

&lt;p&gt;What’s next? Try to remove &lt;strong&gt;empty customers&lt;/strong&gt; from the calculation. Now, this one is a bit tricky—you want to filter it out after you set data types using &lt;em&gt;Transform - Filter node&lt;/em&gt;, but this step is limited to “=, !=, &amp;lt;, &amp;gt;, &amp;lt;=, &amp;gt;=” and using != with Null or empty string is not working...&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C7FAsB-t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cge6yjzm550yogyxba23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C7FAsB-t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cge6yjzm550yogyxba23.png" alt="Remove empty customers" width="652" height="325"&gt;&lt;/a&gt;So maybe you could filter out before you set data types? Well, you can’t do that—before applying data types you can only filter columns for matching values using regex.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9OSj7pXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vjvx4tq3033nli0zj3gb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9OSj7pXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vjvx4tq3033nli0zj3gb.png" alt="Language selection box" width="695" height="240"&gt;&lt;/a&gt;So, what’s left? Once again, you have to use Spark SQL transformation to write a query which will filter out null values. The key function is &lt;em&gt;isnotnull(column) = 1&lt;/em&gt;. I placed this step after applying data types and before filtering out discounts.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kqhfGlR6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fm5npzsovrhjeu257gij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kqhfGlR6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fm5npzsovrhjeu257gij.png" alt="Spark SQL transformation" width="880" height="400"&gt;&lt;/a&gt;Next, let’s handle the number of partitions of output files. And here I have to give up—&lt;strong&gt;it can’t be accomplished without using custom transformation&lt;/strong&gt; (well, at least I didn’t figure out how to do that.) Is it tough?&lt;/p&gt;

&lt;p&gt;Well, it depends. The documentation (AWS doc: &lt;a href="https://docs.aws.amazon.com/glue/latest/ug/edit-jobs-transforms.html#transforms-custom"&gt;transforms custom&lt;/a&gt;) is not very extensive and contains only one example. The most important thing to remember is that the &lt;em&gt;Custom Transformation node&lt;/em&gt; only accepts &lt;em&gt;glueContext&lt;/em&gt; and &lt;em&gt;DynamicFrameCollection&lt;/em&gt; as input and must also return &lt;em&gt;DynamicFrameCollections&lt;/em&gt; (collections of &lt;em&gt;DynamicFrames&lt;/em&gt;) as output.&lt;/p&gt;

&lt;p&gt;What does it mean? It means that in order to perform any transformations, in the first step you have to choose which &lt;em&gt;DynamicFrame&lt;/em&gt; you want to work on. If the transform has only one parent, there is no problem—you choose the first one and convert &lt;em&gt;DynamicFrame&lt;/em&gt; to &lt;em&gt;DataFrame&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def reducePartitionNumber(glueContext, dfc) -&amp;gt; DynamicFrameCollection:
  df = dfc.select(list(dfc.keys())[0]).toDF()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you can do whatever Spark transformations you might want. In my case, I want to reduce the number of partitions created, so I do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df_w_less_partitions = df.coalesce(1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I convert the dataframe back to &lt;em&gt;DynamicFrame&lt;/em&gt; and return it as the &lt;em&gt;DynamicFrames&lt;/em&gt; collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df_one_partition = DynamicFrame.fromDF(df_w_less_partitions, glueContext, "one_part_df")
return DynamicFrameCollection({"CustomTransform0": df_one_partition}, glueContext)

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

&lt;/div&gt;



&lt;p&gt;To sum up, the node should look like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cnYBJ8e---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9jrgqk2n6hap80cqu6cu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cnYBJ8e---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9jrgqk2n6hap80cqu6cu.png" alt="Node should look like this" width="880" height="217"&gt;&lt;/a&gt;But that’s not the end. According to the documentation and what you saw above, &lt;em&gt;“A custom code transform returns a collection of DynamicFrames, even if there is only one DynamicFrame in the result set,”&lt;/em&gt; and, unfortunately, output nodes &lt;strong&gt;do not&lt;/strong&gt; accept DynamicFrameCollection as input, so you will have to add one more a step that will select a specific DynamicFrame from the collection.&lt;/p&gt;

&lt;p&gt;For this step you can use &lt;em&gt;SelectFromCollection&lt;/em&gt; transform node which allows you to indicate which dataset you want to use. Since there is only one parent node here, there is only one dataset to choose from.&lt;/p&gt;

&lt;p&gt;But if this node had several parents or a parent returning many &lt;em&gt;DynamicFrames&lt;/em&gt; (for example SplitFields transformation, which splits dataframe into two separate dataframes), you would have a choice.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GSpdIRTJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jz9enosksy0t0vfyiwru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GSpdIRTJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jz9enosksy0t0vfyiwru.png" alt="SelectFromCollection" width="708" height="339"&gt;&lt;/a&gt;With that done, we can move on to the last task: adding customer information to the dataframe with aggregates. My analysts loaded the customers.csv file into the main folder &lt;em&gt;aws-glue-demo-202109&lt;/em&gt;. File contains the following data: &lt;em&gt;id, name, surname, address&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In our job, we first add another source that will directly reference the CSV file contained in S3 bucket. I give this node the name Customers. AWS Glue Studio detects data formats, separators and defines data types by itself.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xl4X484x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ckgwyh2l0lyjgkrue9x5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xl4X484x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ckgwyh2l0lyjgkrue9x5.png" alt="Image description" width="880" height="436"&gt;&lt;/a&gt;Then we will use the &lt;em&gt;Transform - Join node&lt;/em&gt; to combine the data from the two sources. This type requires at least two parent nodes, so I’m adding &lt;em&gt;aggByCustomers&lt;/em&gt; node as the second source.&lt;/p&gt;

&lt;p&gt;Why am I joining here? Well, I’m afraid that joining after reducing the number of partitions (with the &lt;em&gt;getReducedDynamicFrame node&lt;/em&gt;) will once again result in multiple partitions, and joining earlier (before the aggregate is performed) is less efficient, since that joining would be performed on larger number of rows.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mGR_qwsj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yz7k9zy0dx9494myslco.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mGR_qwsj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yz7k9zy0dx9494myslco.png" alt="Transform - join node" width="880" height="249"&gt;&lt;/a&gt;Now you need to select the join type and declare join conditions. Since my left dataset is &lt;em&gt;Customers&lt;/em&gt; node, right is &lt;em&gt;aggByCustomers&lt;/em&gt; and I know that I don’t have data for all customers, I chose &lt;em&gt;right join&lt;/em&gt;. I join those datasets using &lt;em&gt;columns id&lt;/em&gt; and &lt;em&gt;customer_id&lt;/em&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aOho9as_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87axiyjd4qpa19o7pxs5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aOho9as_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87axiyjd4qpa19o7pxs5.png" alt="Join type" width="716" height="529"&gt;&lt;/a&gt;The last thing to do is to change the parent output of &lt;em&gt;reducePartitionsNumber&lt;/em&gt; from &lt;em&gt;aggByCustomers&lt;/em&gt; to &lt;em&gt;joinAggregatesWithCustomers&lt;/em&gt; and you are good to go. Now the job should look like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ARTtdRIG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fj1yyounkjydho0kpnt0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ARTtdRIG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fj1yyounkjydho0kpnt0.png" alt="Finished node" width="486" height="803"&gt;&lt;/a&gt;Let’s run it and see what happens. Once the job is finished, go to S3 and...&lt;/p&gt;

&lt;p&gt;...it’s working! You received only two files:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--06iJmnLu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3lr4s6zi3pb5mx2zk6ia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--06iJmnLu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3lr4s6zi3pb5mx2zk6ia.png" alt="Received files" width="880" height="76"&gt;&lt;/a&gt;In the first one, you’ll have customers with their data (if found) and aggregates:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q14dqKqh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6hsbte5lv7fe56crz1cs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q14dqKqh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6hsbte5lv7fe56crz1cs.png" alt="First file - customers with their data" width="509" height="90"&gt;&lt;/a&gt;In the second one, you’ll have returned items:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---o4DoAOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yyk7e6a8kah7ofedhb1t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---o4DoAOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yyk7e6a8kah7ofedhb1t.png" alt="Second file - returned items" width="801" height="91"&gt;&lt;/a&gt;Well, frankly speaking I do not like the order of the columns, because when join did not find the client’s data, it looks like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WyAUi4To--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/66rlyxr8mecvc0s8xptf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WyAUi4To--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/66rlyxr8mecvc0s8xptf.png" alt="Join did not find client's data output" width="425" height="47"&gt;&lt;/a&gt;And I don’t see any other way to reorder them than another Spark SQL node, where I would just select the columns in a different order. But let’s leave it as-is. Optionally, I could also use a &lt;em&gt;FillMissingValues&lt;/em&gt; ​​transformer node and type, for example, &lt;em&gt;“NOT_FOUND”&lt;/em&gt; to fill missing values and make the file more readable.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to schedule an AWS Glue job?
&lt;/h2&gt;

&lt;p&gt;At this point, you could say: “Okay, but I don’t want to edit and run my job manually every day.” There are two things that should be set up to automate the whole process.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Automate crawler, so newly added files are visible as consecutive partitions. You don’t have to create a new crawler—you can edit an existing one. Choose a crawler, click &lt;em&gt;Action -&amp;gt; Edit Crawler&lt;/em&gt; and hit &lt;em&gt;Next&lt;/em&gt; until you reach step number #5 (Create a scheduler for this crawler.) Choose &lt;em&gt;Daily&lt;/em&gt; instead of &lt;em&gt;Run from demand&lt;/em&gt; and then you can set up the time.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r15n0EKG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tiijuolhd2lo1iu72f4q.png" alt="Automate crawler" width="674" height="218"&gt;We go through the next steps and save changes. If everything’s gone well, you should see that a scheduler appeared in the crawler:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CW3GPpV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5c4fj2ws0e6cahqo40ji.png" alt="Schedule crawler" width="880" height="23"&gt;
&lt;/li&gt;
&lt;li&gt;The second thing is job automation. First, create a job scheduler, which is a relatively simple task. Go to the created job and click the &lt;em&gt;Scheduler&lt;/em&gt; tab. You’ll immediately see the options to create a new scheduler:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V2RS9ivP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9f1hu7pj65tf9x3xd27c.png" alt="Scheduler tab" width="880" height="231"&gt;You can set up a scheduler name, choose its frequency (Hourly, Daily, Weekly, Monthly, Custom) and, optionally, add a description. I set up a job scheduler to run one hour after the Glue scheduler.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AxmR1bIU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qmcufvevkyu2bqnifp6r.png" alt="Details of schedule" width="880" height="235"&gt;Now, it would be great if you did not have to manually change the date for which the aggregates are to be made. The easiest solution would be to modify the &lt;em&gt;Partition predicate&lt;/em&gt; function in the source node, so it automatically extracts year, month and day from the current date.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;year == year(current_date) AND 
month == month(current_date) AND 
day == day(current_date)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; please keep in mind that &lt;strong&gt;the months and days are not integer values&lt;/strong&gt; (01, 02, 03, etc.), and Spark functions &lt;em&gt;Extracts the month as an &lt;strong&gt;integer&lt;/strong&gt; from a given date/timestamp/string&lt;/em&gt;. So, you would have to once again reorganize your bucket structure.&lt;/p&gt;

&lt;p&gt;For those interested in more advanced solutions, please read about passing custom parameters to Glue Job (since AWS Glue Studio also allows you to pass up to 50 custom parameters) in this article on &lt;a href="https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-python-calling.html?icmpid=docs_glue_studio_helppanel#aws-glue-programming-python-calling-parameters"&gt;Calling AWS Glue APIs in Python—AWS Glue&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you use AWS Glue Studio?
&lt;/h2&gt;

&lt;p&gt;You might be wondering when you should use AWS Glue Studio. Let’s focus on Glue Studio, not Glue as a whole service.&lt;/p&gt;

&lt;p&gt;AWS Glue Studio is great if you want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;quickly create ETL jobs that run regularly,&lt;/li&gt;
&lt;li&gt;combine large amounts of data from many different sources,&lt;/li&gt;
&lt;li&gt;and perform &lt;em&gt;simple&lt;/em&gt; transformations such as rename or drop fields, join, split, or filter dataframe. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since you can see and copy the code, a job prepared in Studio could be used as a starting point for a larger, more complex job in Glue.&lt;/p&gt;

&lt;p&gt;And when is it not that useful? For instance, when you are looking for a job orchestrator that allows you to repeat your work from any step, use sensors to wait for a file, among other things, you will be better off with Step Functions or Airflow. If you are looking for a data preparation tool, DataBrew would be a better choice since it offers way more data transformation options.&lt;/p&gt;

&lt;p&gt;Also, please keep in mind that AWS Glue Studio is not free. When you create a job you have to declare the number of workers (a minimum of two) and choose one of the two possible instance types: G.X1 or G.X2. In G.X1, each worker maps to one DPU and one executor, which launches with eight Spark cores and 10 GiB of memory. G.X2 doubles those values. And you are charged an hourly rate based on the number of DPUs used to run your ETL jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the pros and cons of AWS Glue Studio?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;One of the main advantages of AWS Glue Studio is the fact that, except for just one step, I didn’t need to use any programming language to create the above-mentioned ETL job.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What is not obvious can often be played around with a Spark SQL query. Integrating AWS Glue Studio with S3 or Data Catalog and scheduling jobs is extremely easy, and the same applies to job scheduling. Besides, let’s not forget that you can get data from streaming services like Kinesis or Kafka.&lt;/p&gt;

&lt;p&gt;What’s more, in AWS Glue Studio we can monitor all the jobs in one view, and &lt;em&gt;Job bookmarks&lt;/em&gt; is a very handy feature, too.&lt;/p&gt;

&lt;p&gt;The main disadvantage is definitely the UI, which is a bit clumsy. It can hang and behave unpredictably at times. Since you can’t manually move nodes, larger jobs might be unclear at some point.&lt;/p&gt;

&lt;p&gt;For users unfamiliar with Spark, the limited number of transforms might be a big pain in some cases. And, the latest version does not support all features such as &lt;em&gt;Data Preview&lt;/em&gt;, which is something you will find out only when you try to run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts on building complex data pipelines with AWS Glue Studio
&lt;/h2&gt;

&lt;p&gt;Here is what you’ve accomplished by following the instructions in this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;took files from both Data Glue Catalog and S3 directly, &lt;/li&gt;
&lt;li&gt;applied data types, &lt;/li&gt;
&lt;li&gt;removed unwanted data,&lt;/li&gt;
&lt;li&gt;divided the data based on certain values,&lt;/li&gt;
&lt;li&gt;did some joins and aggregations,&lt;/li&gt;
&lt;li&gt;reduced the number of partitions,&lt;/li&gt;
&lt;li&gt;saved the results to desired paths in an S3 bucket.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you’ve seen in this tutorial, building complex data pipelines doesn’t need to be challenging. I hope you’ve enjoyed following the instructions and learnt a bit more about AWS Glue Studio.&lt;/p&gt;

&lt;p&gt;Here are some other articles you might find useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.stxnext.com/blog/python-for-data-engineering/"&gt;Python for Data Engineering: Why Do Data Engineers Use Python?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stxnext.com/blog/docker-jupyterlab-apache-livy-rest-api-apache-spark/"&gt;How to Build a Spark Cluster with Docker, JupyterLab, and Apache Livy—a REST API for Apache Spark&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stxnext.com/blog/machine-learning-implementation-project-management/"&gt;Machine Learning Implementation and Project Management: A How-To Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;In the article, I used a dataset provided by Dua, D. and Graff, C. (2019). UCI Machine Learning Repository [&lt;a href="http://archive.ics.uci.edu/ml"&gt;http://archive.ics.uci.edu/ml&lt;/a&gt;]. Irvine, CA: University of California, School of Information and Computer Science.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>How to Build a Good API That Won’t Embarrass You</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sun, 03 Apr 2022 17:06:02 +0000</pubDate>
      <link>https://dev.to/stx-next/how-to-build-a-good-api-that-wont-embarrass-you-5hi2</link>
      <guid>https://dev.to/stx-next/how-to-build-a-good-api-that-wont-embarrass-you-5hi2</guid>
      <description>&lt;p&gt;Everyone and their puppy wants an API these days. APIs first gained popularity around 20 years ago. Roy Fielding introduced the term REST in his doctoral dissertation in the year 2000. It was the same year that Amazon, Salesforce and eBay introduced their APIs to developers around the world, forever changing the way that we build software.&lt;/p&gt;

&lt;p&gt;Before REST, the principles in Roy Fielding’s dissertation were known as the “HTTP object model”, and you’ll see why that’s important soon. &lt;/p&gt;

&lt;p&gt;As you read on, you’ll also &lt;strong&gt;see how to determine if your API is mature, what are the main qualities of a good API, and why you should focus on adaptability when building APIs.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The basics of RESTful architecture
&lt;/h2&gt;

&lt;p&gt;REST stands for Representational State Transfer, and it has long been the holy grail of APIs for services, first defined by Roy Fielding in his dissertation. It’s not the only way to build APIs, but it’s the kind of standard that even non-developers know about thanks to its popularity.&lt;/p&gt;

&lt;p&gt;There are six key characteristics of RESTful software:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Client-Server architecture&lt;/li&gt;
&lt;li&gt;Statelessness&lt;/li&gt;
&lt;li&gt;Cacheability&lt;/li&gt;
&lt;li&gt;Layered system&lt;/li&gt;
&lt;li&gt;Code on demand (optional)&lt;/li&gt;
&lt;li&gt;Uniform interface&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But that’s too theoretical for daily usage. We want something more actionable, and that’s going to be the API maturity model.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Richardson Maturity Model
&lt;/h2&gt;

&lt;p&gt;Developed by Leonard Richardson, this model combines the principles of RESTful development into four easy-to-follow steps.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RD-LrQZM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ta8gsxy9m33sx96im16k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RD-LrQZM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ta8gsxy9m33sx96im16k.png" alt="The Richardson Maturity Model" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
The higher you are in the model, the closer you get to the original idea of RESTful as defined by Roy Fielding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 0: The swamp of POX
&lt;/h3&gt;

&lt;p&gt;A level 0 API is a set of plain XML or JSON descriptions. In the introduction, I mentioned that before Fielding’s dissertation, RESTful principles were known as the “HTTP object model”.&lt;/p&gt;

&lt;p&gt;That’s because the HTTP protocol is the most important part of RESTful development. REST revolves around the idea of using as many inherent properties of HTTP as possible.&lt;/p&gt;

&lt;p&gt;At level 0, you don’t use any of that stuff. You just build your own protocol and use it as a proprietary layer. This architecture is known as Remote Procedure Call (RPC), and it’s good for remote procedures / commands. &lt;/p&gt;

&lt;p&gt;You usually have one endpoint you can call upon to receive a bunch of XML data. One example of this is the SOAP protocol:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6htsSEd7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ruvcu72vzxf4vglwprir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6htsSEd7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ruvcu72vzxf4vglwprir.png" alt="SOAP protocol" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Another good example is the Slack API.&lt;/strong&gt; It is a bit more diverse, it has several endpoints, but it’s still an RPC-style API. It exposes various functions of Slack without any added features in-between. The code below allows you to post a message to a specific channel.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3qib6mIH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1lg16v58x4e3hmeaaxvr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3qib6mIH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1lg16v58x4e3hmeaaxvr.png" alt="Slack API" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
Even though it’s a level 0 API according to Richardson’s model, it doesn’t mean it’s bad. As long as it’s usable and properly serves the business needs, it’s a great API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 1: Resources
&lt;/h3&gt;

&lt;p&gt;To build a level 1 API, you need to find nouns in your system and expose them through different URLs, like in the example below.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wL5i60Qh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a08o4u5w4bi9lvjzhwvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wL5i60Qh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a08o4u5w4bi9lvjzhwvw.png" alt="Level 1: Resources" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
/api/books will take me to the general book directory. /api/profile will take me to the profile of the author of those books—if there’s only one of them. To get the first specific instance of a resource, I add an ID (or another reference) to the URL.&lt;/p&gt;

&lt;p&gt;I can also nest the resources in the URLs, and show that they’re organized in a hierarchy.&lt;/p&gt;

&lt;p&gt;Going back to the Slack example, here’s how it would look like as a level 1 API:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m4oOLnR2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbm2by1mfcjwvjmxkde9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m4oOLnR2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbm2by1mfcjwvjmxkde9.png" alt="Level 1 API - Slack example" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
The URL changed; instead of /api/chat.postMessage, now we have /api/channels/general/messages.&lt;/p&gt;

&lt;p&gt;The “channel” part of the information has been moved from the body to the URL. It literally says that using this API, you can expect a message to be posted to the general channel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 2: HTTP verbs
&lt;/h3&gt;

&lt;p&gt;A level 2 API leverages HTTP verbs to add more meaning and intention. There are quite a few of these verbs, I’ll just use a fundamental subset: PUT / DELETE / GET / POST.&lt;/p&gt;

&lt;p&gt;With these verbs, we expect different behaviors from URLs containing them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;POST—create new data &lt;/li&gt;
&lt;li&gt;PUT—update existing data&lt;/li&gt;
&lt;li&gt;DELETE—remove data&lt;/li&gt;
&lt;li&gt;GET—find the data output of a specific id, fetch a resource (or an entire collection)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or, using the previous /api/books example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3LpM0i9A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nrv1cd5pfsajfbvmh387.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3LpM0i9A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nrv1cd5pfsajfbvmh387.png" alt="/api/books example" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;What does “safe” and “idempotent” mean?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A “safe” method is one that will never change data. REST recommends that GET should only fetch data, so it’s the only safe method in the above set. No matter how many times you call a REST-based GET method, it should never change anything in the database. But it’s not inherent in the verb—it’s about how you implement it, so you need to make sure that this works. All other methods will change data in different ways, and can’t be used at random. In REST, GET is both safe and idempotent.&lt;/p&gt;

&lt;p&gt;An “idempotent” method is one that won’t produce different results over many uses. DELETE should be idempotent according to REST—if you delete a resource once and then call DELETE for the same resource a second time, it shouldn’t change anything. The resource should already be gone. POST is the only non-idempotent method in REST specifications, so you can POST the same resource several times and you’ll get duplicates.&lt;/p&gt;

&lt;p&gt;Let’s revisit the Slack example, and see what it would look like if we used HTTP verbs in it to do more operations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vRzgKRlg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ln8a2fzgeej0p31om90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vRzgKRlg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ln8a2fzgeej0p31om90.png" alt="Slack API verbs" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
We could use POST to send a message to the general channel. We could fetch messages from the general channel with GET. We could delete messages with a specific ID with DELETE—which gets interesting because messages are not tied to specific channels, so I might want to design a separate API for removing messages. This example shows that it’s not always easy to &lt;a href="https://rapidapi.com/blog/api-design/"&gt;design an API&lt;/a&gt;; there are plenty of options to choose and trade-offs to make.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 3: HATEOAS
&lt;/h3&gt;

&lt;p&gt;Remember text-only computer games, without any graphics? You just had a lot of text with descriptions of where you are, and what you can do next. To progress, you had to type your choice. That’s kind of what HATEOAS is.!&lt;br&gt;
&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yobes82somhtlq0xx68n.png"&gt;Text game API&lt;/a&gt;&lt;em&gt;HATEOAS stands for “Hypermedia as the Engine of Application State”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you have HATEOAS, whenever someone uses your API they can see other things they can do with it. HATEOAS answers the question, “Where can I go from here?”&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Srh2Ne0Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zk47bcxvp0fxq1i7chci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Srh2Ne0Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zk47bcxvp0fxq1i7chci.png" alt="hateoas example" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
But that’s not all. HATEOAS can also model data relationships. We can have a resource, and we don’t have authors nested in the URL—but we can post the links, so if someone’s interested in authors, they can go there and explore.&lt;/p&gt;

&lt;p&gt;This is not as popular as other levels of the maturity model, but some developers use it. One example is Jira. Below is a chunk from their search API:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_ZZDpyw4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vuysgeiloizn9r21trpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_ZZDpyw4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vuysgeiloizn9r21trpn.png" alt="Jira API" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
They nest links to other resources you can explore, as well as a list of transitions for this issue. Their API is quite interesting because of the “expand” parameter at the top. It allows you to choose fields where you don’t want links, and prefer the full content instead.&lt;/p&gt;

&lt;p&gt;Another example of using HATEOAS is Artsy. Their API heavily relies on HATEOAS. They also use JSON Plus call specifications, which imposes a special convention of structuring links. Below is an example of pagination, one of the coolest examples of using HATEOAS.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WH3h46vH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6rngmr5rnsi3lxqje03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WH3h46vH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6rngmr5rnsi3lxqje03.png" alt="Artsy hateoas" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
You can provide links to next, previous, first, last pages, as well as other pages you find necessary. This simplifies the consumption of an API, because you don’t need to add the URL parsing logic to your client, or a way to append the page number. You just get the client ready to use already structured links.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes a good API
&lt;/h2&gt;

&lt;p&gt;So much for Richardson’s model, but that’s not all that makes a good API. What are other important qualities?&lt;/p&gt;

&lt;h3&gt;
  
  
  Error/exception handling
&lt;/h3&gt;

&lt;p&gt;One of the fundamental things I expect from an API that I consume is that there needs to be an obvious way to tell if there’s an error or an exception. I need to know if my request was processed or not.&lt;/p&gt;

&lt;p&gt;Lo and behold, HTTP also has an easy way to do that: HTTP Status Codes.&lt;/p&gt;

&lt;p&gt;The basic rules governing status codes are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2xx is OK&lt;/li&gt;
&lt;li&gt;3xx means your princess is in another castle—the resource you’re looking for is in another place&lt;/li&gt;
&lt;li&gt;4xx means the client did something wrong&lt;/li&gt;
&lt;li&gt;5xx means the server failed
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FgbrnK4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pj8k2xbcuxadbpc7v8f3.png" alt="500 internal server error" width="694" height="555"&gt;
&lt;strong&gt;At the very least, your API should provide 4xx and 5xx status codes.&lt;/strong&gt; 5xx are sometimes generated automatically. For example, the client sends something to the server, it’s an invalid request, the validation is flawed, the issue goes down the code and we have an exception—it will return a 5xx status code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to commit to using specific status codes, you’ll find yourself wondering, “Which code is best for this case?” That question isn’t always easy to answer.&lt;/p&gt;

&lt;p&gt;I recommend you go to RFC which specifies these status codes, they give a wider explanation than other sources, and tell you when these codes are appropriate etc. Luckily, there are several resources online that will help you choose, like this H&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"&gt;TTP status code guide from Mozilla.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;Great APIs have great documentation. The biggest problem with documentation is usually finding someone to update it as the API grows. One great option is self-updating documentation that isn’t detached from the code.&lt;/p&gt;

&lt;p&gt;For example, comments aren’t connected to the code. When the code changes, the comments stay the same and become obsolete. They can be worse than no comments at all, because after a while they’ll be providing false information. Comments don’t update automatically, so developers need to remember to maintain them alongside the code.&lt;/p&gt;

&lt;p&gt;Self-updating documentation tools solve this problem. One popular tool for this is &lt;a href="https://swagger.io/docs/specification/about/"&gt;Swagger&lt;/a&gt;, a tool built around the OpenAPI specification which makes it easy to describe your API.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RItFtVDI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4bt6mvpqs49eomd1t7d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RItFtVDI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4bt6mvpqs49eomd1t7d.png" alt="Swagger API" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
The cool part of Swagger is that it’s executable, so you can play around with the API and instantly see what it does and how it changes.&lt;/p&gt;

&lt;p&gt;To add self-updating to Swagger, you need to use other plugins and tools. In Python there are plugins for most major frameworks. They generate descriptions of how API requests should be structured, and define what data comes in and what comes out.&lt;/p&gt;

&lt;p&gt;What if you don’t want Swagger, and prefer something simpler? A popular alternative is Slate—a static API you can build and expose on your URL.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GKJ-FKm7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwh4t3u0s0t7x0vhkxt0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GKJ-FKm7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwh4t3u0s0t7x0vhkxt0.png" alt="Slate API documentation" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
Something in-between that’s also worth recommending is a combination of &lt;a href="https://github.com/Mermade/widdershins"&gt;widdershins&lt;/a&gt; and &lt;a href="https://api2html.com/docs/overview/"&gt;api2html&lt;/a&gt;. It’ll allow you to generate Slate-like docs from Swagger’s definition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cacheability
&lt;/h3&gt;

&lt;p&gt;Cacheability may not be a big deal in some systems. You might not have a lot of data that can be cached, everything changes all the time, or maybe you don’t have a lot of traffic.&lt;/p&gt;

&lt;p&gt;But in most cases, cacheability is crucial for good performance. It’s relevant to RESTful APIs because the HTTP protocol has a lot to do with cache, for example HTTP headers allow you to control cache behaviour.&lt;/p&gt;

&lt;p&gt;You might want to cache things on the client side, or in your application if you have a registry or value store to keep data. But HTTP allows you to get a good cache essentially for free, so if it’s possible—don’t walk away from a free lunch.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---uXSXjbP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/magl96h2h9km5n673zar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---uXSXjbP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/magl96h2h9km5n673zar.png" alt="HTTP Cacheability" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
Also, since caching is part of the HTTP spec, a lot of things that participate in HTTP will know how to cache things: browsers, which support caching natively, as well as other intermediary servers between you and the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evolutionary API design
&lt;/h2&gt;

&lt;p&gt;The most important part of building APIs, and modern software in general, is adaptability. Without adaptability, development time slows down, and it becomes harder to ship features in a reasonable time, especially when you're facing deadlines.&lt;/p&gt;

&lt;p&gt;“Software architecture” means different things in different contexts, but let’s adopt this definition for now:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Software architecture: the act/art of dodging decisions that prevent change in the future.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With that in mind, when you design your software and have to choose between options with similar benefits, you should always choose the one that’s more future-proof. &lt;/p&gt;

&lt;p&gt;Good practices aren’t everything. Building the wrong thing in the right way is not what you want to do. It’s better to adopt a growth mindset and accept the fact that change is inevitable, especially if your project is going to continue growing.&lt;/p&gt;

&lt;p&gt;To make your APIs more adaptable, one of the key things to do is to keep your API layers thin. The real complexity should be shifted down.&lt;/p&gt;

&lt;h2&gt;
  
  
  APIs shouldn’t dictate the implementation
&lt;/h2&gt;

&lt;p&gt;Once you publish a public API, it’s done, it’s immutable, you can’t touch it. But what can you do if you have no other choice but to commit to a weirdly designed API?&lt;/p&gt;

&lt;p&gt;You should always look for ways to simplify your implementation. Sometimes controlling your APIs response format with a special HTTP header is a leaner solution compared to building another API and calling it v2.&lt;/p&gt;

&lt;p&gt;APIs are just another layer of abstraction. They shouldn’t dictate the implementation. There are several development patterns that you can apply in order to avoid this issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  API gateway
&lt;/h3&gt;

&lt;p&gt;This is a facade-like development pattern. If you break up a monolith into a bunch of microservices, and want to expose some functionalities to the world, you simply build an API gateway that acts like a facade.&lt;/p&gt;

&lt;p&gt;It will provide a uniform interface for the different microservices (which may have different APIs, use different error formats, etc).&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend for frontend
&lt;/h3&gt;

&lt;p&gt;If you have to build one API to satisfy a bunch of different clients, it might be difficult. Decisions for one client will impact the functionality for others.&lt;/p&gt;

&lt;p&gt;Backend for frontend says—if you have different clients that like different APIs, say mobile apps which like GraphQL, just build it for them.&lt;/p&gt;

&lt;p&gt;This works only if your API is a layer of abstraction, and it’s thin. If it’s coupled to your database, or it’s too big, with too much logic, you won’t be able to do this.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL vs. RESTful
&lt;/h2&gt;

&lt;p&gt;There’s a lot of hype for GraphQL. It’s kind of the new kid on the block, but it has already gathered a lot of fans. So much so, that some developers claim that it will dethrone REST.&lt;/p&gt;

&lt;p&gt;Even though GraphQL is much newer compared to the RESTful specification, they share a lot of similarities. &lt;strong&gt;The biggest downside of GraphQL is cacheability—it has to be implemented in the client or in the application.&lt;/strong&gt; There are client-libraries out there that have caching capabilities built-in (like &lt;a href="https://www.apollographql.com/docs/react/caching/cache-configuration/"&gt;Apollo&lt;/a&gt;), but it’s still harder than using the almost-free cacheability provided by HTTP. &lt;/p&gt;

&lt;p&gt;Technically, GraphQL is level 0 in terms of the Richardson model, but it has qualities of a good API. You might not be able to use several HTTP functionalities, but GraphQL is built to solve specific problems.&lt;/p&gt;

&lt;p&gt;One killer use for GraphQL is aggregating different APIs, and exposing them as one GraphQL API.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zxAalcFr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wjcvqqy2aseqzmv8a9a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zxAalcFr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wjcvqqy2aseqzmv8a9a.png" alt="GraphQL killer usage" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;GraphQL does wonders with underfetching and overfetching,&lt;/strong&gt; which are issues where REST APIs can be difficult to manage. Both are related to performance—if you underfetch, you’re not using API calls efficiently, so you have to make a lot of them. When you overfetch, your calls take result in a bigger data transfer than necessary, which is a waste of bandwidth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The comparison of REST vs. GraphQL is a great segue into summarizing the most important qualities of a good API.&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--is-NqArl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kpk4vvn3vcsr9opokcza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--is-NqArl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kpk4vvn3vcsr9opokcza.png" alt="Features of good API" width="880" height="496"&gt;&lt;/a&gt;&lt;br&gt;
You need a clear representation for data—RESTful gives you that in the form of resources.&lt;/p&gt;

&lt;p&gt;You need a way to show which operations are available—RESTful does that by combining resources with HTTP verbs.&lt;/p&gt;

&lt;p&gt;There needs to be a way to confirm that there’s an error/exception—HTTP status codes do this, possibly with responses that explain them.&lt;/p&gt;

&lt;p&gt;It’s nice to have discoverability and possibility to navigate—in RESTful, HATEOAS takes care of that.&lt;/p&gt;

&lt;p&gt;It’s important to have great documentation—in this case executable, self-updating docs can take care of that, which goes beyond the RESTful spec.&lt;/p&gt;

&lt;p&gt;Last but not least—great APIs should have cacheability, unless your specific case dictates that it’s not necessary.&lt;/p&gt;

&lt;p&gt;The biggest difference between REST and GraphQL is the way they handle cacheability. When you build your API the REST way, you get HTTP cacheability essentially for free. If you choose GraphQL, you need to worry about adding a cache to your client or your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;This article was based on a recent presentation by Sebastian Buczyński. Check out his blog &lt;a href="https://breadcrumbscollector.tech/"&gt;Breadcrumbs Collector&lt;/a&gt; and grab his ebook &lt;a href="https://cleanarchitecture.io/"&gt;Implementing the Clean Architecture&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more reading about APIs, check out &lt;a href="https://phil.tech/"&gt;Phillip Sturgeon’s blog&lt;/a&gt; or his great book called &lt;a href="https://www.amazon.com/Build-APIs-You-Wont-Hate-ebook/dp/B07HNFVRNH"&gt;Build APIs You Won’t Hate&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>api</category>
    </item>
    <item>
      <title>Step-by-Step: An Agile Product Validation Process Using Impact Mapping</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Tue, 29 Mar 2022 19:23:03 +0000</pubDate>
      <link>https://dev.to/stx-next/step-by-step-an-agile-product-validation-process-using-impact-mapping-22dk</link>
      <guid>https://dev.to/stx-next/step-by-step-an-agile-product-validation-process-using-impact-mapping-22dk</guid>
      <description>&lt;p&gt;While working on various IT projects, I realized that regardless of all these “lean” product development movements, many companies still encounter major issues in terms of product validation. In other words, it’s hard for people to understand if the product they develop is what the market needs.&lt;/p&gt;

&lt;p&gt;To help you with your validation efforts, I’d like to give you an inside look into the day-by-day Agile product validation process for a live product that we have worked out with one of our clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is product validation?
&lt;/h2&gt;

&lt;p&gt;Let’s start by answering the fundamental question: what is product validation?&lt;/p&gt;

&lt;p&gt;There are many approaches to what’s called &lt;strong&gt;“product validation.”&lt;/strong&gt; Try to Google the phrase and you will find that there is more than one way to define it. My short explanation would be that &lt;strong&gt;product validation is a process aimed at answering the following question: is my product something that people need?&lt;/strong&gt; When you build a product, it’s a good practice to verify its value each time you release a new version&lt;/p&gt;

&lt;p&gt;One of the most famous frameworks in this field was presented in The Lean Startup by Eric Ries (you can find it on our &lt;a href="https://stxnext.com/blog/2017/06/28/10-must-read-books-ctos/"&gt;list of must-read books for CTOs&lt;/a&gt;). He suggests following these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build&lt;/strong&gt; an experiment to test if people need what you are trying to sell them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Measure&lt;/strong&gt; the result of your experiment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learn&lt;/strong&gt; your lesson and then iterate by building your next experiment.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What I like about this approach is that Eric reveals that in order to gain value out of the cycle, you should plan it in the reverse order. First you need to know what you want to learn about your users. Next, you should think about how you will measure it. It's only at the end that you should try to figure out how to build the fastest and cheapest experiment to gain that knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  An inside look at our team’s product validation process
&lt;/h2&gt;

&lt;p&gt;I personally think that product validation is one of the greatest challenges in the whole workflow. In the project I'm currently work on, we encountered the same challenge. However, we decided to structure a process that would support our validation. We don’t call our approach the lean startup framework, although ultimately it does include the 3 aforementioned steps: build, measure, learn.&lt;/p&gt;

&lt;p&gt;What does our validation process look like?&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The pre-development phase: “how to measure?”
&lt;/h3&gt;

&lt;h3&gt;
  
  
  a) The Product Owner (PO) adds their idea of validation to the user story.
&lt;/h3&gt;

&lt;p&gt;(Not sure what a PO does? Read our article about &lt;a href="https://stxnext.com/blog/2017/05/31/product-owner-responsibilities-path-junior-expert/"&gt;Product Owner's responsibilities.&lt;/a&gt;) Every time our PO adds a new user story to the product backlog, they have to fill in the “how to measure?” field. This approach helps them analyze, prior to any further discussion, how to recognize if the change we're about to make is something that our users need, and if we have enough tools to allow user story validation. See the snapshot of our user story template below—this is the “planning” part of our framework.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mKvRdMwH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4eivafx71gjfheaqx3g8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mKvRdMwH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4eivafx71gjfheaqx3g8.png" alt="Snapshot of user story template" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  b) The validation idea is discussed with other people during the weekly meeting.
&lt;/h3&gt;

&lt;p&gt;The meeting should be attended by the Product Owner, UX designer, Scrum Master, and the client’s representative (optionally).&lt;/p&gt;

&lt;p&gt;The way we run this session is very easy: the PO presents their idea for validation while the other participants discuss it and suggest improvements where applicable. This way, the PO receives a wide range of opinions and makes more informed decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Development phase
&lt;/h3&gt;

&lt;p&gt;No validation work is done during this stage. This is the “build” part of the lean startup framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Post-development phase: product validation
&lt;/h3&gt;

&lt;p&gt;After the new product increment is deployed to production, our validation process starts. Some of it happens ad-hoc—our data analysts start producing stats. However, the main point of the process is a weekly meeting during which the Product Owner, UX designer, Scrum Master, and, optionally, the client’s representative, discuss what has been released to our “live” environment and what results it's generated. In other words, we validate whether the new product features had a positive, neutral, or negative impact on end users. For this purpose, we use Google Analytics, a heatmap tool, and other data analysis tools.&lt;/p&gt;

&lt;p&gt;After we collect the necessary data and validate new features, we make decisions regarding future development plans. We use a Jira board to facilitate the meeting (see below). We take the items that are in the “To verify” column and try to move them to “Verified,” which means that we have actually validated our feature. These are the the “measure” and the “learn” parts of the lean startup framework.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jsvy766S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2oafd6p55dtk0z84i5sw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jsvy766S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2oafd6p55dtk0z84i5sw.png" alt="Post development phase" width="880" height="228"&gt;&lt;/a&gt;We iterate these practices and the cycle starts from the beginning every next development sprint. To summarize, the validation workflow is presented on the graph below.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BxoNJy1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cmyftwjeusxoiimhuuly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BxoNJy1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cmyftwjeusxoiimhuuly.png" alt="Validation workflow" width="447" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an impact map and how do we use it?
&lt;/h2&gt;

&lt;p&gt;Aside from Jira mentioned in the example above, we use one additional tool to visualize product validation status—the impact map.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact mapping&lt;/strong&gt; is startegic planning technique created by Gojko Adzic to help businesses achieve their goals. &lt;/p&gt;

&lt;p&gt;(We were quite excited to see &lt;a href="https://twitter.com/STXNext/status/882577070844522496"&gt;Gojko Adzic himself&lt;/a&gt; retweet this article soon after it was published.)&lt;/p&gt;

&lt;p&gt;The idea is simple. First, you define a business goal, e.g. “Sell our product to a million clients within 3 months.” Gojko suggests thinking about impact mapping as if it were an exercise in navigating a map from point A to point B. In this case, point A would be where we are right now, and point B is the goal we would like to reach.&lt;/p&gt;

&lt;p&gt;If we look at the map, there are usually many ways to reach the same goal. The idea is to hit the road and check if all the roads are passable. It might turn out that some are actually closed, or there may be roads that don’t exist just yet.&lt;/p&gt;

&lt;p&gt;Using impact mapping terms, you are supposed to define 4 elements:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Goal
&lt;/h3&gt;

&lt;p&gt;Decide what would you like to achieve from the business perspective. Maybe you'd like to reach a certain volume of sales in a given period of time, or maybe you'd prefer to focus on the number of new registered users. Whatever your goal is, try to define it as precisely as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Actors
&lt;/h3&gt;

&lt;p&gt;Think about various groups of people who can help you achieve the goal. These can be your segments of users, your employees or anyone else.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Impacts
&lt;/h3&gt;

&lt;p&gt;At this stage, you need to think about the actions your actors can take to help you achieve the goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Deliverables
&lt;/h3&gt;

&lt;p&gt;Try to define precise product features that will help actors make an impact. &lt;/p&gt;

&lt;p&gt;An example could look like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--92CJ2RPl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11a4zm2s31ju5ldqgimc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--92CJ2RPl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11a4zm2s31ju5ldqgimc.png" alt="Deliverables" width="500" height="100"&gt;&lt;/a&gt;If creating a deliverable drives actors to make an impact that supports our main goal, we validate this deliverable positively. Using that information, we then plan our future work. If a deliverable doesn’t create any positive change, we validate it negatively, which is also a significant part of our learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example of what our impact map looks like
&lt;/h2&gt;

&lt;p&gt;The central part of the impact map (dark blue) presents the main goal we'd set as a team. It can be any sort of a business goal, e.g. 100,000 new users registered in our application in the next 3 months. It should be something precise and easy to measure at the end of the specified period.&lt;/p&gt;

&lt;p&gt;On the borders of our impact map, we presented the deliverables (yellow, red, black, and green) we would like to offer to the end users in order to support our main goal, e.g. a free gift for everyone who registers within the specified period. In the Agile environment, deliverables would be called user stories or product backlog items.&lt;/p&gt;

&lt;p&gt;The colors of the deliverables carry additional meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;yellow—&lt;/strong&gt;for all deliverables that were added to the impact map and are in the pre-development stage,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;black—&lt;/strong&gt;the deliverable is either in the development or post-development stage but prior to the validation stage,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;green—&lt;/strong&gt;the deliverable was validated positively,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;red—&lt;/strong&gt;the deliverable was validated negatively.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--871ac7FB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6i6f19vhjyvme1hu4ad.png" alt="Group of users" width="690" height="704"&gt;In our case, the impact map is updated weekly and overseen by the Scrum Master. However, the Product Owner or anyone else familiar with it can make sure the map stays up to date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on the information we have visualized on the impact map, we make data-driven decisions about the future development of the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the benefits of impact mapping?
&lt;/h2&gt;

&lt;p&gt;Impact mapping has a number of advantages your software house can greatly benefit from. Among others, impact mapping:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;helps maximize customer value and minimize waste by making it easier for teams to focus on the objectives they’re working to reach;&lt;/li&gt;
&lt;li&gt;visualizes the process in an accessible way for everyone involved;&lt;/li&gt;
&lt;li&gt;increases collaboration within the team and unlocks creativity by facilitating the collective creation and testing of assumptions;&lt;/li&gt;
&lt;li&gt;facilitates horizontal working, rather than top-to-bottom;&lt;/li&gt;
&lt;li&gt;helps the team align their work with business objectives;&lt;/li&gt;
&lt;li&gt;makes it easy for team members to spot challenges immediately and respond to them in a timely manner, as well as adapt to changing circumstances;&lt;/li&gt;
&lt;li&gt;keeps the focus on people, their experiences and ideas. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;To recap, here’s a few reasons why impact mapping for Agile product validation is definitely worth your time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating an impact map helps the team remain focused on the business goals, i.e. the actions that actually create revenue.&lt;/li&gt;
&lt;li&gt;It allows you to see the whole landscape of all possible routes toward your business goal—including faster, easier, cost-effective routes you may have missed.&lt;/li&gt;
&lt;li&gt;Impact mapping opens you up to more creative decisionmaking; you can look at whole sections of the map and be able to see which sections have been effective and which ones you should give more consideration to. &lt;/li&gt;
&lt;li&gt;There's always a different section of the map you can focus on. &lt;/li&gt;
&lt;li&gt;Thinking with the map helps you stay motivated.
Hopefully this post will help you organize your product validation process within your team. Good luck, and let us know how it goes!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>agile</category>
      <category>product</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why Use React Native for Your Mobile App?</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sun, 27 Mar 2022 22:28:38 +0000</pubDate>
      <link>https://dev.to/stx-next/why-use-react-native-for-your-mobile-app-h6</link>
      <guid>https://dev.to/stx-next/why-use-react-native-for-your-mobile-app-h6</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Jakub Grajcar and Bartek Klukaczewski&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What are your plans to capitalize on the growing mobile market?&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://www.statista.com/statistics/269025/worldwide-mobile-app-revenue-forecast/"&gt;statista.com&lt;/a&gt;, by the year 2020 mobile apps are set to generate $188.9 billion USD in global revenues via app stores and in-app advertising. That’s a huge opportunity for business.&lt;/p&gt;

&lt;p&gt;It’s high time to start utilizing the mobile market. But users have already seen dozens of apps on their smartphones. What can you show them that’s impressive, works great and seamlessly integrates with their mobile OS?&lt;/p&gt;

&lt;p&gt;One solution at your disposal is React Native.&lt;/p&gt;

&lt;p&gt;This article will tell you &lt;strong&gt;what React Native is&lt;/strong&gt; and &lt;strong&gt;why (or why not) you should consider it&lt;/strong&gt; for your mobile project.&lt;/p&gt;

&lt;p&gt;To dig deeper into the subject of React Native, I spoke with Bartosz Kazuła, one of our JavaScript developers. Before he joined STX Next, Bartosz was already a big fan of React Native, and used it to create features for a text-based browser game. Now, he’s using his expertise to solve the business problems of our clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is React Native?
&lt;/h2&gt;

&lt;p&gt;React Native is a framework that allows you to build native mobile apps using JavaScript. Normally, you’d need to program your mobile app using Java (for Android) and Swift/Obj-C (for iOS). React Native removes that requirement, leading to fully functional apps on both platforms in much less time and using just one coding language.&lt;/p&gt;

&lt;p&gt;Is React Native an entirely new invention? Not exactly. The framework was developed only a few years ago, by a social media company you may have heard of…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--icGoMmrE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfknbp7c1byua5ig08ct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--icGoMmrE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfknbp7c1byua5ig08ct.png" alt="Facebook logo" width="880" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Facebook is the company behind both ReactJS and React Native. In fact, Facebook first created React to build the social platform we all love to hate. After further development, Facebook released ReactJS for the web as open source.&lt;/p&gt;

&lt;p&gt;But Facebook was still struggling with their mobile app. They needed to maintain two codebases: one for iOS, one for Android. Features implemented in Swift on iOS had to be implemented separately in Java on Android, leading to work duplication and asymmetrical apps.&lt;/p&gt;

&lt;p&gt;React Native neatly solves that problem.&lt;/p&gt;

&lt;p&gt;Coming on the heels of ReactJS, the purpose of React Native was to facilitate the creation of mobile apps. It’s simple: if you can code an app once in JavaScript and deploy it both to Android and iOS, your life gets a lot easier.&lt;/p&gt;

&lt;p&gt;If you’ve ever used the official Facebook app on Android or iOS, you’ve seen React Native in action. (Same goes for the mobile Airbnb app.)&lt;/p&gt;

&lt;h2&gt;
  
  
  How popular is React Native in terms of market share?
&lt;/h2&gt;

&lt;p&gt;React Native is rising in popularity as a convenient solution to build cross-platform mobile apps with less strain on your budget.&lt;/p&gt;

&lt;p&gt;How popular is it, exactly?&lt;/p&gt;

&lt;p&gt;Take a look at React Native’s market share:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uH7wm82_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dasxy8xeh6907cazeyz0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uH7wm82_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dasxy8xeh6907cazeyz0.png" alt="Apps that contains React Native" width="880" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The stats are especially telling when you consider the top apps in the App Store and Google Play Store right now. Among the top 500 apps in the US, 14.85% of installed apps are built with React Native.&lt;/p&gt;

&lt;p&gt;In fact, in the category of top US apps, React Native is the third most popular framework, &lt;a href="https://www.appbrain.com/stats/libraries/tag/app-framework/android-app-frameworks?list=top500"&gt;right after Kotlin and Android Architecture Components&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use React Native?
&lt;/h2&gt;

&lt;p&gt;For a long time, React Native was considered to be commercially unviable. It wasn’t developed or supported enough to produce “native-like” apps.&lt;/p&gt;

&lt;p&gt;But the times have changed. React Native is gaining popularity, gaining community support, and gaining more market share. It’s getting easier and easier to write brilliant apps using React Native—and the world is taking notice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tried and trusted
&lt;/h3&gt;

&lt;p&gt;Facebook built React Native first and foremost to create a fantastic mobile app for their own social portal. More likely than not, you’ve used it on your phone by way of the Facebook mobile app. Does it feel like a native app? Sure it does.&lt;/p&gt;

&lt;p&gt;But since React Native has gone open-source, more companies have decided to bet on it and create their mobile apps this way. Here are just a few examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Popular React Native apps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Facebook&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instagram&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skype&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tesla&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Walmart&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discord&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bloomberg&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Putting your app in such company isn’t the worst idea in the world.&lt;/p&gt;

&lt;h3&gt;
  
  
  One codebase for two platforms
&lt;/h3&gt;

&lt;p&gt;With React Native, you create one codebase that works on both Android and iOS. And it doesn’t just “work”—&lt;strong&gt;it compiles to native Java and Swift code.&lt;/strong&gt; Specifically, React Native creates a bridge between web UI components and their native Java/Swift counterparts.&lt;/p&gt;

&lt;p&gt;Think about the implications for your software project. No need for two development teams for two platforms. No need to synchronize features and layouts. You simply develop faster and can get more out of your budget.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the language you already know
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;You need less specialized knowledge to create React Native apps.&lt;/strong&gt; Chances are you already have someone on your team that can program in JavaScript, possibly even in ReactJS specifically. JS developers are simply easier to find compared to developers with skills in Java or Swift.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6I2tdOKs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j3bsww3m9o4jc0bwn45i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6I2tdOKs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j3bsww3m9o4jc0bwn45i.png" alt="Programming languages - Stack Overflow 2017 Developer Survey" width="687" height="540"&gt;&lt;/a&gt;&lt;em&gt;Stack Overflow 2017 Developer Survey&lt;/em&gt;&lt;br&gt;
Even if your frontend developer has never used React Native, with some self-education they can get up to speed very quickly, especially if they’ve used React already. All you need is a little time googling to find out which web components correspond with which mobile components—and you’re set.&lt;/p&gt;

&lt;h3&gt;
  
  
  Growing all the time
&lt;/h3&gt;

&lt;p&gt;React Native is under active development. Both Facebook and the massive community around React Native are constantly working on improvements for the framework. If you can’t solve a problem right now because React Native doesn’t have the solution, in a few months the situation might be different.&lt;/p&gt;

&lt;p&gt;For example, Bartosz was recently faced with the task of implementing a “speedometer” component for one of his projects. His initial idea was to create such a component by himself. But first, he decided to check if someone from the community had the same need in the past. Lo and behold, he found an open license speedometer ready to use, saving him time.&lt;/p&gt;

&lt;p&gt;Even Microsoft took notice of React Native, prompting them to create their own fork: &lt;a href="https://github.com/Microsoft/react-native-windows"&gt;React Native for Windows&lt;/a&gt;. Their solution allows developers to more easily create apps for Windows 10, Windows 10 Mobile, and Xbox One.&lt;/p&gt;

&lt;h3&gt;
  
  
  Save even more time with a web app
&lt;/h3&gt;

&lt;p&gt;If you have a ReactJS web app, fragments of the frontend code (such as business logic) can be shared between mobile and web, facilitating development even more.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s an example of a React Native app?
&lt;/h2&gt;

&lt;p&gt;Bloomberg, the business and financial news provider, decided to use React Native to create its new consumer app after initial testing and prototyping.&lt;/p&gt;

&lt;p&gt;Previously, Bloomberg engineers had to develop iOS and Android versions separately, without being able to share the code they created. Switching to React Native saved them time as they could unify their development capabilities and each developer could focus on one feature at a time. As a result, the team managed to create the new app in five months—about half the usual development time.&lt;/p&gt;

&lt;p&gt;Using React Native also allowed the company to add a number of new, interactive features to the app, such as the ability to swipe a headline to share or bookmark an article. Users can also access live TV and on-demand event feeds.&lt;/p&gt;

&lt;p&gt;The app allows users to customize it extensively, including personalizing content according to their interests and location, and monitoring their own personal portfolios.&lt;/p&gt;

&lt;p&gt;The React Native design automates code refreshes and, instead of recompiling, it reloads the app instantly.&lt;/p&gt;

&lt;p&gt;According to a senior software engineer at Bloomberg who worked on the transition, “React Native is the best out there,” and the company would be using it again in other mobile apps.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--47MbWpRR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vtt9zfn53z3a1u8yeyxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--47MbWpRR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vtt9zfn53z3a1u8yeyxg.png" alt="Bloomberg" width="300" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What should you watch out for when using React Native?
&lt;/h2&gt;

&lt;p&gt;As with any solution, React Native has its drawbacks. What should you be wary of?&lt;/p&gt;

&lt;h3&gt;
  
  
  React Native is not 100% native...
&lt;/h3&gt;

&lt;p&gt;Despite what Facebook might try to tell you, React Native apps are not equivalent to true native apps written entirely in Swift/Obj-C or Java.&lt;/p&gt;

&lt;p&gt;Let’s take the native Gmail as an example. The Gmail app includes a worker that checks your inbox. Your Gmail account is synced with the whole mobile system, not just the app. Gmail also knows that if you’re on mobile data, not WiFi, it should sync less often.&lt;/p&gt;

&lt;p&gt;With React Native you’re not integrated so closely with the system—at least not out of the box. Your account will be stored in the app, not the system. It’s also harder to take into account WiFi versus mobile data. For some apps, this will not be a problem; for others, it might be game-changing.&lt;/p&gt;

&lt;h3&gt;
  
  
  ...but you can make it as native as you need
&lt;/h3&gt;

&lt;p&gt;When you choose to use React Native, you don’t have to use it exclusively. You can still use React for most of the app, and native for the crucial pieces that need to integrate 100% with the native system.&lt;/p&gt;

&lt;p&gt;One of our prospective clients recently argued against React Native, saying it’s still not the same as a true native app. Our counterargument was simple: it doesn’t have to be the same. With a little additional work, you can make it “as native as you need” by adding some Java/Swift code for specific cases and features.&lt;/p&gt;

&lt;h3&gt;
  
  
  If you use React Native, you have to use React
&lt;/h3&gt;

&lt;p&gt;This might be obvious, but it still needs to be said as a disclaimer. When you opt for React Native, you will have to use ReactJS to create your app. React has competitors for a reason; it’s not always the best choice.&lt;/p&gt;

&lt;p&gt;Fortunately, there are some competing solutions that fulfill a similar purpose to React Native without locking you down. One such competitor is &lt;a href="https://stxnext.com/blog/2018/11/22/react-native-vs-ionic-comparison/"&gt;Ionic&lt;/a&gt;. Their community isn’t as active, nor is it growing so quickly. But Ionic has one advantage: you can use different JS frameworks with it, including Angular, Vue.js and even React if you need some parts of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Badly written JavaScript or heavy calculations could hurt your performance
&lt;/h3&gt;

&lt;p&gt;(Thanks to &lt;a href="https://www.facebook.com/StxNext/posts/1279701738836786?comment_id=1279717692168524&amp;amp;comment_tracking=%7B%22tn%22%3A%22R%22%7D"&gt;Adrian Warkocz&lt;/a&gt; for contributing a comment on Facebook that prompted this section.)&lt;/p&gt;

&lt;p&gt;Using JavaScript in itself is a solution that has its drawbacks. For example, if the JavaScript code in your React Native app is poorly written, you will feel the difference more strongly than if your app was a pure native one.&lt;/p&gt;

&lt;p&gt;However, this is a slight drawback that you won't feel if you have &lt;a href="https://stxnext.com/services/react-native/"&gt;skilled React Native developers&lt;/a&gt; on your side.&lt;/p&gt;

&lt;p&gt;Tim Mensch described the tradeoff very well in one of his Quora answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Badly written JavaScript is &lt;strong&gt;slightly&lt;/strong&gt; more likely to be slow than badly written native code. So if your developers are &lt;strong&gt;borderline&lt;/strong&gt;, then you might be &lt;strong&gt;slightly&lt;/strong&gt; better off spending nearly twice as much to develop &lt;strong&gt;two native apps&lt;/strong&gt;. I prefer to hire strong developers, though.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;—Tim Mensch on Quora&lt;/p&gt;

&lt;p&gt;JavaScript may also slow down performance if your app is very calculation-heavy. This is not a very common case for most mobile apps, but still a scenario you should consider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is React Native good for your project?
&lt;/h2&gt;

&lt;p&gt;You’ve now discovered some of the benefits of React Native, but you’re still not sure if you should use it in your project? Here’s what it can help you achieve:&lt;/p&gt;

&lt;h3&gt;
  
  
  Save time and money
&lt;/h3&gt;

&lt;p&gt;If you need to develop an app for both iOS and Android, React Native is the best tool out there. It can reduce the codebase by about 95%, saving you time and money. On top of that, React Native has a number of open-source &lt;a href="https://native.directory/"&gt;libraries&lt;/a&gt; of pre-built components which can help you further speed up the development process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create great mobile apps
&lt;/h3&gt;

&lt;p&gt;React Native is great for mobile apps. It provides a slick, smooth and responsive user interface, while significantly reducing load time. It’s also much faster and cheaper to build apps in React Native as opposed to building native ones, without the need to compromise on quality and functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use existing skills
&lt;/h3&gt;

&lt;p&gt;Since React Native is based on JavaScript, your developers will not need long to get to grips with it. Having said this, it’s an open-source and community-driven framework, so if they ever need support, it’s widely available online.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add third-party plugins
&lt;/h3&gt;

&lt;p&gt;React Native also allows you to easily incorporate third-party plug-ins and APIs, including maps and payment systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;So what should you know about React Native?&lt;/strong&gt; Here are the key takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you’re using the Facebook or Airbnb mobile app, &lt;strong&gt;you’re using React Native without even knowing it.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Native apps are easy to write&lt;/strong&gt;, saving time for developers and cutting costs for project managers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Native apps lower your development and maintenance costs&lt;/strong&gt;, because you don’t have to deal with two separate codebases for iOS and Android.&lt;/li&gt;
&lt;li&gt;Since React Native is just a wrapper for native components, &lt;strong&gt;there’s nothing stopping you from adding native Java or Swift code where you need it.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;At the end of the day, &lt;strong&gt;you’re still coding in JavaScript.&lt;/strong&gt; There’s no need to learn Swift/Java, or to add developers with such skills to your roster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Native is growing fast&lt;/strong&gt; with no signs of stopping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are just some of the many benefits React Native can deliver.&lt;/p&gt;

&lt;p&gt;If you’d like to find out how this framework compares to Ionic or Flutter, you’ll find these pieces useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.stxnext.com/blog/react-native-vs-ionic-comparison/"&gt;React Native vs. Ionic: A Comparison of Pros and Cons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stxnext.com/blog/react-native-vs-flutter-comparison/"&gt;React Native vs. Flutter: A Comparison of Pros and Cons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.statista.com/statistics/269025/worldwide-mobile-app-revenue-forecast/"&gt;https://www.statista.com/statistics/269025/worldwide-mobile-app-revenue-forecast/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://facebook.github.io/react-native/"&gt;https://facebook.github.io/react-native/&lt;/a&gt;&lt;br&gt;
&lt;a href="http://facebook.github.io/react-native/showcase.html"&gt;http://facebook.github.io/react-native/showcase.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://medium.com/react-native-development/a-brief-history-of-react-native-aae11f4ca39"&gt;https://medium.com/react-native-development/a-brief-history-of-react-native-aae11f4ca39&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Microsoft/react-native-windows"&gt;https://github.com/Microsoft/react-native-windows&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.quora.com/Will-an-app-written-entirely-in-React-Native-be-much-slower-than-a-Native-App-What-are-the-differences"&gt;https://www.quora.com/Will-an-app-written-entirely-in-React-Native-be-much-slower-than-a-Native-App-What-are-the-differences&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>reactnative</category>
      <category>mobile</category>
      <category>beginners</category>
    </item>
    <item>
      <title>FastAPI vs. Flask: Comparing the Pros and Cons of Top Microframeworks for Building a REST API in Python</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sat, 26 Mar 2022 19:56:06 +0000</pubDate>
      <link>https://dev.to/stx-next/fastapi-vs-flask-comparing-the-pros-and-cons-of-top-microframeworks-for-building-a-rest-api-in-python-mcf</link>
      <guid>https://dev.to/stx-next/fastapi-vs-flask-comparing-the-pros-and-cons-of-top-microframeworks-for-building-a-rest-api-in-python-mcf</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Adam Stempniak and Daniel Różycki&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Creating web applications such as REST APIs is the bread and butter of backend developers. Therefore, working with a web framework should be quick and easy.&lt;/p&gt;

&lt;p&gt;Microframeworks are a great start for small projects, MVPs, or even large systems that need a REST API—including Flask and FastAPI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I wrote an application to create, update, download, and delete news in these two frameworks. As a result, here’s my comparison of FastAPI and Flask.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Flask? Why use it?
&lt;/h2&gt;

&lt;p&gt;Flask is one of the most popular libraries for building web applications in Python. People who start their adventure with programming will easily find a lot of Flask tutorials and solutions to common problems.&lt;/p&gt;

&lt;p&gt;It is lightweight (a “microframework”) and very well documented, with many extensions and a large community.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is FastAPI? Why use it?
&lt;/h2&gt;

&lt;p&gt;FastAPI ranks among the &lt;a href="https://fastapi.tiangolo.com/#performance" rel="noopener noreferrer"&gt;highest-performing Python web frameworks&lt;/a&gt; for building APIs out there and it’s being used more and more day by day.&lt;/p&gt;

&lt;p&gt;Its emphasis on speed, not only in terms of the number of queries handled per second, but also the speed of development and its built-in data validation, makes it an ideal candidate for the backend side of our web application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data validation
&lt;/h2&gt;

&lt;p&gt;Here’s where we can find the first significant difference between the two libraries.&lt;/p&gt;

&lt;p&gt;By installing Flask, we don’t get any data validation tool. However, we can work around that by using extensions offered by the community, such as &lt;a href="https://flask-marshmallow.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Flask-Marshmallow&lt;/a&gt; or &lt;a href="https://pythonhosted.org/Flask-Inputs/" rel="noopener noreferrer"&gt;Flask-Inputs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The downside of this solution is that we have to rely on libraries that are developed separately from our main framework, meaning we can’t be 100% sure they will be compatible.&lt;/p&gt;

&lt;p&gt;FastAPI, on the other hand, gives us the &lt;a href="https://pydantic-docs.helpmanual.io/" rel="noopener noreferrer"&gt;Pydantic&lt;/a&gt; library to use, which makes data validation much simpler and faster than typing it by hand. It’s closely related to FastAPI itself, so we can be sure that Pydantic will be compatible with our framework at all times.&lt;/p&gt;

&lt;p&gt;So, what are the validations in the individual libraries based on our simple API?&lt;/p&gt;

&lt;p&gt;We create classes named &lt;code&gt;NewsSchema&lt;/code&gt; / &lt;code&gt;CreatorSchema&lt;/code&gt; that will be the base classes for validating our news and authors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Flask
@dataclass()
class NewsSchema(BaseSchema):
   title: str = ""
   content: str = ""
   creator: CreatorSchema = CreatorSchema()

@dataclass
class CreatorSchema(BaseSchema):
   first_name: str = ""
   last_name: str = ""
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  # FastAPI
   class NewsSchema(BaseModel):
      title: str = ""
      content: str = ""
      creator: CreatorSchema

   class CreatorSchema(BaseModel):
      first_name: str = ""
      last_name: str = ""
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can notice that FastAPI’s &lt;code&gt;NewsSchema&lt;/code&gt; / &lt;code&gt;CreatorSchema&lt;/code&gt; use &lt;code&gt;BaseModel&lt;/code&gt; as a parent class. This is required because &lt;code&gt;BaseModel&lt;/code&gt; comes from the Pydantic library and has the functions necessary for data validation.&lt;/p&gt;

&lt;p&gt;In Flask, however, we inherit from the &lt;code&gt;BaseSchema&lt;/code&gt; class, which is a regular data class and contains several methods the inheriting classes will use or override.&lt;/p&gt;

&lt;p&gt;In our case, we will only check whether the text we enter is within the character limit.&lt;/p&gt;

&lt;p&gt;The validation itself will take place in the &lt;code&gt;NewsSchemaInput&lt;/code&gt; / &lt;code&gt;CreatorSchemaInput&lt;/code&gt; classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; # Flask
   @dataclass()
   class NewsSchemaInput(NewsSchema):
      _errors: dict = field(init=False, default_factory=dict)

      def _validate_title(self) -&amp;gt; None:
         if MIN_TITLE_LEN &amp;gt; len(self.title) &amp;lt; MAX_TITLE_LEN:
            self._errors[
               "title"
            ] = f"Title should be {MIN_TITLE_LEN}-{MAX_TITLE_LEN} characters long"

      def _validate_content(self) -&amp;gt; None:
         if len(self.content) &amp;lt; MIN_CONTENT_LEN:
            self._errors[
               "content"
            ] = f"Content should be minimum {MIN_CONTENT_LEN} characters long"

      def __post_init__(self) -&amp;gt; None:
         self._validate_content()
         self._validate_title()
         try:
            if not isinstance(self.creator, CreatorSchemaInput):
               self.creator = CreatorSchemaInput(**self.creator)
         except ValidationError as err:
            self._errors["creator"] = err.errors
         if self._errors:
            raise ValidationError(
               f"Validation failed on {type(self).__name__}", self._errors
            )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Flask
   @dataclass
   class CreatorSchemaInput(CreatorSchema):
      _errors: dict = field(init=False, default_factory=dict)

      def _validate_first_name(self) -&amp;gt; None:
         if FIRST_NAME_MIN_LEN &amp;gt; len(self.first_name) &amp;lt; FIRST_NAME_MAX_LEN:
            self._errors[
               "first_name"
            ] = f"First name should be {FIRST_NAME_MIN_LEN}-{FIRST_NAME_MAX_LEN} characters long"

      def _validate_last_name(self) -&amp;gt; None:
         if LAST_NAME_MIN_LEN &amp;gt; len(self.last_name) &amp;lt; LAST_NAME_MAX_LEN:
            self._errors[
               "last_name"
            ] = f"Last name should be {LAST_NAME_MIN_LEN}-{LAST_NAME_MAX_LEN} characters long"

      def __post_init__(self) -&amp;gt; None:
         self._validate_first_name()
         self._validate_last_name()
         if self._errors:
            raise ValidationError(
               f"Validation failed on {type(self).__name__}", self._errors
            )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we create our object &lt;code&gt;NewsSchemaInput&lt;/code&gt; / &lt;code&gt;CreatorSchemaInput&lt;/code&gt;, the &lt;code&gt;__post_init__&lt;/code&gt; method will be run, where we execute data validation (checking the text length). If it’s incorrect, we add errors to the &lt;code&gt;_errors&lt;/code&gt; variable, and finally raise a &lt;code&gt;Validation Error&lt;/code&gt; exception.&lt;/p&gt;

&lt;p&gt;In the case of structures that are nested  (&lt;code&gt;CreatorSchemaInput&lt;/code&gt;), we have to create these objects manually. We do it after the &lt;code&gt;NewsSchemaInput&lt;/code&gt; validation is done in the &lt;code&gt;__post_init__&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;The data checking itself is not a big problem—only adding new fields will be cumbersome, because we have to add a separate &lt;code&gt;_validate&lt;/code&gt; method each time. In the case of a nested structure, we have to create an instance of this object and catch an exception.&lt;/p&gt;

&lt;p&gt;We can see that the classes that validate the incoming data become quite extensive—and that’s just for a few keys. We also need to add our own implementation of error handling, so that we can add nested error information in the API responses.&lt;/p&gt;

&lt;p&gt;In FastAPI, it is much simpler and more enjoyable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; # FastAPI
   class NewsSchemaInput(NewsSchema):
      title: str = Field(
         title="Title of the News",
         max_length=MAX_TITLE_LEN,
         min_length=MIN_TITLE_LEN,
         example="Clickbait title",
      )
      content: str = Field(
         title="Content of the News", min_length=50, example="Lorem ipsum..."
      )
      creator: CreatorSchemaInput
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   # FastAPI
   class CreatorSchemaInput(CreatorSchema):
      first_name: str = Field(
         title="First name of the creator",
         min_length=FIRST_NAME_MIN_LEN,
         max_length=FIRST_NAME_MAX_LEN,
         example="John",
      )
      last_name: str = Field(
         title="Last name of the creator",
         min_length=LAST_NAME_MIN_LEN,
         max_length=LAST_NAME_MAX_LEN,
         example="Doe",
      )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By importing &lt;code&gt;Field&lt;/code&gt; from &lt;code&gt;Pydantic&lt;/code&gt;, we have access to simple rules that must be followed for user input to be valid. Data types are also validated on the basis of variable types, so if our &lt;code&gt;first_name&lt;/code&gt; variable has the &lt;code&gt;str&lt;/code&gt; type, we must pass text in the input (and act similarly for all built-in data types).&lt;/p&gt;

&lt;p&gt;Without any extra code, Pydantic does a great job checking nested structures (&lt;code&gt;CreatorSchemaInput&lt;/code&gt; in this case).&lt;/p&gt;

&lt;p&gt;We can find all of this in no more than a few lines of code!&lt;/p&gt;

&lt;p&gt;In addition to &lt;code&gt;max_length&lt;/code&gt; and &lt;code&gt;min_length&lt;/code&gt;, we can also see two additional parameters: &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;example&lt;/code&gt;. They are optional, but will be visible in the automatic documentation generated by FastAPI for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outbound data serialization
&lt;/h2&gt;

&lt;p&gt;Now that we know how to validate the data, we should think about how we want to return it.&lt;/p&gt;

&lt;p&gt;The message will have not only the content, title, and author, but also its unique number (id) and the date it was created and updated. We need to create a new class that will serialize the &lt;code&gt;News&lt;/code&gt; domain model and it will be &lt;code&gt;NewsSchemaOutput&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Flask
   @dataclass
   class NewsSchemaOutput(NewsSchema):
      id: int = 0
      created_at: datetime = datetime.now()
      updated_at: datetime = datetime.now()

      def as_dict(self) -&amp;gt; dict:
         schema_as_dict = super().as_dict()
         schema_as_dict["created_at"] = int(self.created_at.timestamp())
         schema_as_dict["updated_at"] = int(self.updated_at.timestamp())
         return schema_as_dict
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; # FastAPI
   class NewsSchemaOutput(NewsSchema):
      id: int = Field(example="26")
      created_at: datetime = Field(example="1614198897")
      updated_at: datetime = Field(example="1614198897")

      class Config:
         json_encoders = {datetime: lambda dt: int(dt.timestamp())}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;NewsSchemaOutput&lt;/code&gt; class is practically the same in both cases, the only difference being the parent class and the method of serialization to the dictionary (together with changing the &lt;code&gt;datetime&lt;/code&gt; object into timestamp).&lt;/p&gt;

&lt;p&gt;In FastAPI, while using Pydantic, we have the option of adding a &lt;code&gt;Config&lt;/code&gt; class, in which we have placed the &lt;code&gt;json_encoders&lt;/code&gt; variable. It helps to serialize the data in the way that we require. In this case, we want to pass the date object as a timestamp. In Flask, however, we had to change the data in the already created dictionary into those that we want to return.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating views and defining data
&lt;/h2&gt;

&lt;p&gt;Setting up messages in both libraries is very similar and uses a simple decorator on the function we want to use. However, the ways of defining data validation and serialization differ.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; # Flask
   @news_router.route("/news", methods=["POST"])
   def add_news():
      db_repo = get_database_repo()
      news_schema = NewsSchemaInput(**request.get_json())
      news_dto = NewsDTO.from_news_schema(news_schema=news_schema)
      saved_news = db_repo.save_news(news_dto=news_dto)
      output_schema = NewsSchemaOutput.from_entity(news=saved_news).as_dict()
      return output_schema, HTTPStatus.CREATED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; # FastAPI
   @news_router.post(
      "/news",
      response_model=NewsSchemaOutput,
      summary="Create the news",
      status_code=status.HTTP_201_CREATED,
   )
   async def add_news(
      news_input: NewsSchemaInput,
      db_repo: DatabaseRepository = Depends(get_database_repo),
   ):
      """
      Create the news with following information:

      - **title**: Title of news
      - **content**: News content
      - **creator**: Creator of content
      """
      news_dto = NewsDTO.from_news_schema(news_schema=news_input)
      db_news = await db_repo.save_news(news_dto=news_dto)
      return db_news.as_dict()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the very beginning, we have a decorator that specifies the path and the HTTP method that will be handled. Flask sets it using the &lt;code&gt;methods&lt;/code&gt; parameter, where we need to pass the list of supported methods, while FastAPI uses the &lt;code&gt;post&lt;/code&gt; attribute on &lt;code&gt;news_router&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The decorator FastAPI uses is not only used to determine the HTTP path and methods, but also to serialize the data (&lt;code&gt;response_model&lt;/code&gt;), describe the view in automatic documentation (&lt;code&gt;summary&lt;/code&gt;), define the response status (&lt;code&gt;status_code&lt;/code&gt;), and much more—not all of its functions have been included in this example.&lt;/p&gt;

&lt;p&gt;It can be said that FastAPI not only defines the access path and method, but also describes the whole view in depth. But what’s really going on in this view? Let’s start with Flask!&lt;/p&gt;

&lt;p&gt;The first thing we do is get the database repository for our function with: db_repo = get_database_repo ()&lt;/p&gt;

&lt;p&gt;In the next step, we validate the data submitted by the user, which are in the &lt;code&gt;request&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   db_repo = get_database_repo()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   news_schema = NewsSchemaInput(**request.get_json())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line will raise a &lt;code&gt;ValidationError&lt;/code&gt; exception if the input is invalid.&lt;/p&gt;

&lt;p&gt;The exception will be caught in the &lt;code&gt;errorhandler&lt;/code&gt; we created and Flask will return a reply with all errors that are in the &lt;code&gt;_errors&lt;/code&gt; variable on &lt;code&gt;NewsSchemaInput&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But hold on just a second! We haven’t yet discussed the &lt;code&gt;errorhandler&lt;/code&gt; we supposedly created.&lt;/p&gt;

&lt;p&gt;In Flask and FastAPI, we can add our own exception handling, which will be thrown in the views implementation. They look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; # Flask
   @app.errorhandler(ValidationError)
   def handle_validation_error(exc: ValidationError) -&amp;gt; Tuple[dict, int]:
      status_code = HTTPStatus.UNPROCESSABLE_ENTITY
      return {"detail": exc.errors}, status_code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# FastAPI
   @app.exception_handler(ValidationError)
   async def handle_validation_error(request: Request, exc: ValidationError):
      return JSONResponse(
         status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
         content={"detail": exc.errors()},
      )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the validation was successful, create a &lt;code&gt;NewsDTO&lt;/code&gt; object that will pass the necessary information to the database repository. The repository will do its magic (save a message in the database) and return the &lt;code&gt;News&lt;/code&gt; domain object to us, which we then serialize with the &lt;code&gt;NewsSchemaOutput&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; news_dto = NewsDTO.from_news_schema(news_schema=news_schema)
   saved_news = db_repo.save_news(news_dto=news_dto)
   output_schema = NewsSchemaOutput.from_entity(news=saved_news).as_dict()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the very end, we return &lt;code&gt;NewsSchemaOutput&lt;/code&gt; as the dictionary and the response status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   return output_schema, HTTPStatus.CREATED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s take a look at FastAPI. This time, we get two parameters in the view: &lt;code&gt;news_input&lt;/code&gt; and&lt;code&gt;db_repo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the first one, the input data validation happens before the execution of our view method, thanks to the &lt;code&gt;news_input&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;You might be asking yourself: how does FastAPI know which class to use? It’s thanks to typing. The &lt;code&gt;news_input&lt;/code&gt; parameter has the&lt;code&gt;NewsSchemaInput&lt;/code&gt; type, so what FastAPI does is pass all the data to this class that we sent using the POST method. We don’t need to create an instance of the &lt;code&gt;NewsSchemaInput&lt;/code&gt; object because we will get validated data in the &lt;code&gt;news_input&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;Regarding &lt;code&gt;db_repo&lt;/code&gt;, it works similar to Flask, except that here we’re using dependency injection. The &lt;code&gt;Depends&lt;/code&gt; keyword allows you to substitute classes or functions while our application is running. We’ll talk about &lt;code&gt;dependency injection&lt;/code&gt; a bit later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   async def add_news(
      news_input: NewsSchemaInput,
      db_repo: DatabaseRepository = Depends(get_database_repo),
   ):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When our method is called, we save the message in the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   db_news = await db_repo.save_news(news_dto=news_dto)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Flask, we had to create an instance of the &lt;code&gt;NewsSchemaOutput&lt;/code&gt; class to return the correct data. Same with the response status: it’s also returned using the &lt;code&gt;return&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;FastAPI allows you to specify a class to serialize data using the &lt;code&gt;response_model&lt;/code&gt; parameter in the decorator. All we need to do is to provide the correct structure that &lt;code&gt;Pydatnic&lt;/code&gt; will understand. The response status can also be set in the same place as &lt;code&gt;response_model&lt;/code&gt;, but using the&lt;code&gt;status_code&lt;/code&gt; parameter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching messages, variables in the address, and GET parameters
&lt;/h2&gt;

&lt;p&gt;Just as when we create a post, we define the view with a simple decorator. This time, however, we use the GET method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   # Flask
   @news_router.route("/news/&amp;lt;int:news_id&amp;gt;", methods=["GET"])
   def get_news(news_id: int):
      db_repo = get_database_repo()
      news_from_db = db_repo.get_news(news_id=news_id)
      output_schema = NewsSchemaOutput.from_entity(news=news_from_db).as_dict()
      return output_schema
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   # FastAPI
   @router.get(
      "/news/{news_id}",
      response_model=NewsSchemaOutput,
      summary="Get the news by ID",
      responses=NOT_FOUND_FOR_ID,
   )
   async def get_news(
      news_id: int, db_repo: DatabaseRepository = Depends(get_database_repo)
   ):
      """
      Get the news with passed ID
      """
      db_news = await db_repo.get_news(news_id=news_id)
      return db_news.as_dict()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To download the message we’re interested in, we need to pass its id to our view. We do this with an address to which we add the &lt;code&gt;news_id&lt;/code&gt; parameter. In Flask, we have to specify its type in detail using angle brackets and the name, i.e. &lt;code&gt;&amp;lt;int: news_id&amp;gt;&lt;/code&gt;. We’re forced to use only basic types that Flask understands, such as int, uuid, str or float, and so on.&lt;/p&gt;

&lt;p&gt;FastAPI uses a convention that is similar to that used by f-string, where the name of our variable is defined by curly brackets and its type is set in the parameters of the view function.&lt;/p&gt;

&lt;p&gt;This is a more flexible solution, as we can try to pass complicated structures in the address. You may also have noticed a new parameter that has appeared in the view decorator. This parameter is called &lt;code&gt;responses&lt;/code&gt;—we’ll come back to it when we discuss automatic documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtering messages with GET parameters
&lt;/h2&gt;

&lt;p&gt;When we want a flexible solution, instead of creating a view that needs defined variables in the address, we use GET parameters. In this case, we need to return messages that meet the criteria passed to us by the so-called &lt;code&gt;query parameters&lt;/code&gt;. We have two parameters: &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;created_at&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   # Flask
   @news_router.route("/news", methods=["GET"])
   def get_news_by_filter():
      db_repo = get_database_repo()
      ids = request.args.getlist("id", type=int)
      created_at = request.args.getlist("created_at", type=int)
      news_from_db = db_repo.get_news_by_filter(id=ids, created_at=created_at)
      return jsonify(
         [NewsSchemaOutput.from_entity(news=news).as_dict() for news in news_from_db]
      )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   # FastAPI
   @router.get(
      "/news",
      response_model=List[NewsSchemaOutput],
      summary="Get the news by filter",
      responses=NOT_FOUND_FOR_ID,
   )
   async def get_news_by_filter(
      id: Set[int] = Query(set()),
      created_at: Set[datetime] = Query(set()),
      db_repo: DatabaseRepository = Depends(get_database_repo),
   ):
      """
      Get the news with passed filters.

      - **id**: List of id to search for
      - **created_at**: List of date of creation timestamps
      """
      db_news = await db_repo.get_news_by_filter(id=id, created_at=created_at)
      return [news.as_dict() for news in db_news]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flask provides the request object from which we can extract data about the request to our view method. Flask offers a &lt;code&gt;request&lt;/code&gt; object from which we can retrieve all query data to our view.&lt;/p&gt;

&lt;p&gt;This time, we’re interested in the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;created_at&lt;/code&gt; parameters. We also know that we can expect a list of these parameters—for this, we use the &lt;code&gt;getlist&lt;/code&gt; method from the special &lt;code&gt;args&lt;/code&gt; dictionary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   ids = request.args.getlist("id", type=int)
   created_at = request.args.getlist("created_at", type=int)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we send the extracted data to the database repository to get a list of &lt;code&gt;News&lt;/code&gt; domain models, which we turn into a list of dictionaries from the &lt;code&gt;NewsSchemaOutput&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   news_from_db = db_repo.get_news_by_filter(id=ids, created_at=created_at)
   [NewsSchemaOutput.from_entity(news=news).as_dict() for news in news_from_db]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We must also remember that we can’t return the list from the view—it’s necessary to execute the &lt;code&gt;jsonify&lt;/code&gt; function for our endpoint to return the &lt;code&gt;Response&lt;/code&gt; object with the correct serialization of the list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   return jsonify(
         [NewsSchemaOutput.from_entity(news=news).as_dict() for news in news_from_db]
      )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With FastAPI, the whole process looks quite similar to Flask—the difference is that we get the address variables in the function parameters, which is much more readable than executing &lt;code&gt;request.args.getlist&lt;/code&gt; with each variable we need. In order for FastAPI to know that the function parameters are address variables, we need to add the default &lt;code&gt;Query&lt;/code&gt; value to them, which is predefined.&lt;/p&gt;

&lt;p&gt;How does FastAPI know that we want a specific data type if we haven’t specified it in curly brackets? Typing shows it.&lt;/p&gt;

&lt;p&gt;All we need to do is to add a type to our parameters, e.g. &lt;code&gt;set [int]&lt;/code&gt;, and we will be sure that the variable will contain a set with integers only.&lt;/p&gt;

&lt;p&gt;After the address variables are validated, we extract the &lt;code&gt;News&lt;/code&gt; domain models from the database repository using the sent criteria. Then we return the list of message model dictionaries and the &lt;code&gt;response_model&lt;/code&gt; in the decorator will deal with correct serialization of the data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   db_news = await db_repo.get_news_by_filter(id=id, created_at=created_at)
      return [news.as_dict() for news in db_news]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dependency injection
&lt;/h2&gt;

&lt;p&gt;Dependency injection is a pattern in design and software architecture based on removing direct dependencies between components.&lt;/p&gt;

&lt;p&gt;Sounds pretty complicated, right? Well, FastAPI was able to implement this pattern in a very simple way.&lt;/p&gt;

&lt;p&gt;We may have noticed that in each view, there is something like this in the function parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   db_repo: DatabaseRepository = Depends(get_database_repo)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what we call a dependency injection—in this case, we’re injecting the database repository. The &lt;code&gt;Depends&lt;/code&gt; keyword is able to inject anything that can be named (e.g. classes or functions). This is a good method, as it allows you to stick to the DRY (Don’t Repeat Yourself) rule, because you don’t have to create a new variable for the database repository each time, as it is done in Flask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   db_repo = get_database_repo()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another advantage of &lt;code&gt;Depends&lt;/code&gt; is that &lt;a href="https://fastapi.tiangolo.com/advanced/testing-dependencies/" rel="noopener noreferrer"&gt;it can easily substitute implementations in tests&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Flask, to replace the return value from &lt;code&gt;get_database_repo&lt;/code&gt;, we would have to mock this function every time we run tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   @mock.patch("path.to.dependency.get_database_repo)
   def test_some_view(db_repo_inject_mock):
      db_repo_inject_mock.return_value = OUR OWN DB REPO IMPLEMENTATION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to dependency injection in FastAPI. we can use…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   app.dependency_overrides[db_repo] = OUR OWN CALLABLE IMPLEMENTATION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…to replace the implementation when running the tests.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Depends&lt;/code&gt; can also be used to not repeat the same function parameters n times. For more, take a look at the &lt;a href="https://fastapi.tiangolo.com/tutorial/dependencies/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronicity
&lt;/h2&gt;

&lt;p&gt;Unfortunately, Flask doesn’t support asynchronicity and ASGI interface, which means that some long-running queries may block our application. This is related to a smaller number of users we can handle with our REST API.&lt;/p&gt;

&lt;p&gt;As you may have noticed, the view functions in FastAPI start with &lt;code&gt;async&lt;/code&gt; and each method calling on the database repository is preceded by the word &lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;FastAPI is fully asynchronous—which doesn’t mean it’s required, since we can also implement ordinary synchronous functions—and uses the ASGI interface. Thanks to that, we can use non-blocking queries to databases or external services, which means the number of simultaneous users using our application will be much larger than in the case of Flask.&lt;/p&gt;

&lt;p&gt;In its documentation, FastAPI has a very well written example of using &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt;. I highly recommend &lt;a href="https://fastapi.tiangolo.com/async/" rel="noopener noreferrer"&gt;reading it&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;And how about running a benchmark?&lt;/p&gt;

&lt;p&gt;For this task, we will use &lt;a href="https://fastapi.tiangolo.com/async/" rel="noopener noreferrer"&gt;Locust&lt;/a&gt;. It’s a free, open-source Python load testing tool. Our test will be based on adding 100 users to the pool of active connections every second, until we reach 2,000 users at the same time.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpetgvdpbv76inqroag2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpetgvdpbv76inqroag2n.png" alt="Locust - Flask"&gt;&lt;/a&gt; &lt;em&gt;Flask&lt;/em&gt;&lt;br&gt;
As we can see, the number of queries per second we can handle is around 633. That’s not bad, right? It could be better, though. The average waiting time for a response is about 1,642 ms—practically one and a half seconds to receive any data from the API is definitely too much. To this, we can add 7% of unsuccessful queries.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc4sqvl6vq9skqggvbre.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc4sqvl6vq9skqggvbre.png" alt="Locus - FastAPI"&gt;&lt;/a&gt;&lt;em&gt;FastAPI&lt;/em&gt;&lt;br&gt;
FastAPI did much better in this task. The number of queries that we can handle is about 1,150 per second (almost twice as much as in Flask), and the average waiting time for a response is only… 14 ms. All queries were correct and we didn’t spot any errors.&lt;/p&gt;
&lt;h2&gt;
  
  
  Automatic documentation
&lt;/h2&gt;

&lt;p&gt;When creating a REST API, documentation is essential for a team of developers or users who want to use this interface to communicate with our application.&lt;/p&gt;

&lt;p&gt;You can do it manually, e.g. in the Jira Confluence / Github wiki or any other design data collection tool. However, there is a risk of human error, e.g. when someone forgets to update the addresses to views or makes a typo.&lt;/p&gt;

&lt;p&gt;The most common standard for creating such documentation is &lt;a href="https://github.com/OAI/OpenAPI-Specification" rel="noopener noreferrer"&gt;OpenAPI&lt;/a&gt; and &lt;a href="https://json-schema.org/" rel="noopener noreferrer"&gt;JSONSchema&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Flask offers extensions, such as &lt;a href="https://pypi.org/project/flask-swagger/" rel="noopener noreferrer"&gt;Flask-Swagger&lt;/a&gt; or &lt;a href="https://github.com/flasgger/flasgger" rel="noopener noreferrer"&gt;Flasgger&lt;/a&gt;, which operate using the specification mentioned above. They require additional installation and knowledge of the format used by these standards.&lt;/p&gt;

&lt;p&gt;Also, the specifications of the transferred data must be saved manually—they will not be taken from the classes that validate or the parameters that we download.&lt;/p&gt;

&lt;p&gt;FastAPI has documentation that is fully compatible with OpenAPI and JSONSchema, which is created automatically from Pydantic schemas and function parameters or GET variables. The user interface is provided by &lt;a href="https://swagger.io/tools/swagger-ui/" rel="noopener noreferrer"&gt;SwaggerUI&lt;/a&gt; and &lt;a href="https://github.com/Redocly/redoc" rel="noopener noreferrer"&gt;Redoc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is a very interesting feature, as it doesn’t require any work from us (unless we want to embellish our documentation with details). All the rules for the required data can be found in the Pydatnic schemas.&lt;/p&gt;

&lt;p&gt;Documentation is available at &lt;code&gt;host / doc&lt;/code&gt; (SwaggerUI) and &lt;code&gt;host / redoc&lt;/code&gt; (ReDoc) and looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyomj2qi94opvj99i6w8x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyomj2qi94opvj99i6w8x.png" alt="Automatic documentation - SwaggerUI - FastAPI"&gt;&lt;/a&gt;&lt;em&gt;Swagger UI&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pefe6m3aqrkqzcci2h1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pefe6m3aqrkqzcci2h1.png" alt="Automatic documentation - SwaggerUI - ReDoc"&gt;&lt;/a&gt;&lt;br&gt;
In SwaggerUI, we also have access to all the schemas that we have defined in our application:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1tbw5rtartepiay6p1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1tbw5rtartepiay6p1o.png" alt="Schemas"&gt;&lt;/a&gt;&lt;br&gt;
We can notice that the information from the &lt;code&gt;summary&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt; parameters from &lt;code&gt;CreatorSchemaInput&lt;/code&gt; appeared.&lt;/p&gt;

&lt;p&gt;How does FastAPI know what information to pass to the documentation? Let’s look at an example of downloading messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   # FastAPI
   @router.get(
      "/news/{news_id}",
      response_model=NewsSchemaOutput,
      summary="Get the news by ID",
      responses=NOT_FOUND_FOR_ID,
   )
   async def get_news(
      news_id: int, db_repo: DatabaseRepository = Depends(get_database_repo)
   ):
      """
      Get the news with passed ID
      """
      db_news = await db_repo.get_news(news_id=news_id)
      return db_news.as_dict()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are parameters in the decorator that will be taken into account when creating documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/ news / {news_id}&lt;/code&gt;—in the documentation, we will see that the &lt;code&gt;news_id&lt;/code&gt; parameter is required and must be an integer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;response_model&lt;/code&gt;—this response scheme will be automatically displayed in the documentation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;responses&lt;/code&gt;—if our view returns response codes other than 200/400/422 or 500, we can add a special dictionary with the statuses and the returned data schema, like here:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   NOT_FOUND_FOR_ID: Response_Type = {
      404: {
         "description": "News with given ID wasn't found",
         "content": {
            "application/json": {"example": {"detail": "News with id {id} don't exist"}}
         },
      }
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, the docstring is taken into account and will be shown as additional information for the specific view.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhgz63pq4esb5fekzx5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhgz63pq4esb5fekzx5d.png" alt="Automatic documentation - docstring"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts on Flask and FastAPI
&lt;/h2&gt;

&lt;p&gt;Thanks for reading my comparison of these two great libraries using a very simple CRUD application from a REST API as an example.&lt;/p&gt;

&lt;p&gt;On the one hand, we have the very popular Flask, which can’t be ignored; on the other, there is FastAPI, which wins the hearts of users with the number of built-in functionalities and asynchronicity.&lt;/p&gt;

&lt;p&gt;So, which one is better? Personally, if I were to pick the framework for my next REST project, I’d certainly lean toward FastAPI.&lt;/p&gt;

&lt;p&gt;Of course, you’re free to draw your own conclusions and choose differently. However, I hope you’ll at least try to give FastAPI a chance.&lt;/p&gt;

</description>
      <category>python</category>
      <category>fastapi</category>
      <category>flask</category>
      <category>api</category>
    </item>
    <item>
      <title>DevOps Tools Overview: Monitoring Cloud Infrastructure with CloudWatch and OpsGenie</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sat, 19 Mar 2022 14:01:28 +0000</pubDate>
      <link>https://dev.to/stx-next/devops-tools-overview-monitoring-cloud-infrastructure-with-cloudwatch-and-opsgenie-29g3</link>
      <guid>https://dev.to/stx-next/devops-tools-overview-monitoring-cloud-infrastructure-with-cloudwatch-and-opsgenie-29g3</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Lidia Kurasińska&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For your business to perform at an optimal level, you need to take a proactive approach to in-depth monitoring and analysis of your key asset: the product you’re offering.&lt;/p&gt;

&lt;p&gt;Server crashes and unexpected downtime mean frustrated users and lost revenue. Therefore, being able to detect any issues in your IT infrastructure before they escalate and monitor failure patterns will go a long way toward making sure you &lt;strong&gt;deliver seamless performance to your end users.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But infrastructure monitoring is not only about minimizing disruption. By providing you with in-depth insights about your product, it will enable you to better understand its day-to-day performance and make data-driven, long-term decisions about its future.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stxnext.com/services/devops/"&gt;Based on our experience&lt;/a&gt; of helping clients monitor their infrastructure 24/7, we wrote this post to help you understand the importance of having reliable monitoring tools and mechanisms in place.&lt;/p&gt;

&lt;p&gt;In our collaboration with our partners, we’ve used mainly Amazon CloudWatch and OpsGenie, so we’ll focus on these two tools. However, many of their underlying principles can be replicated with other monitoring services available on the market.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is infrastructure monitoring?
&lt;/h2&gt;

&lt;p&gt;Infrastructure monitoring refers to the process of collecting and reviewing data about your infrastructure’s status and performance.&lt;/p&gt;

&lt;p&gt;Some of the monitored metrics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the load levels of, for instance, CPU or RAM;&lt;/li&gt;
&lt;li&gt;the status of services that run on the server (e.g. the application or the database);&lt;/li&gt;
&lt;li&gt;the number of errors that have occurred in certain services (e.g. the 5xx error code on the NGINX server).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The collected data can come from various sources: from the application itself to the computer that hosts it. Gathering this information is the basis of infrastructure monitoring, as it allows administrators to define the server’s status and configure the alerts that provide notifications on any unusual performance.&lt;/p&gt;

&lt;p&gt;By gathering a wealth of data, infrastructure monitoring tools give administrators the necessary insight to protect the business and plan ahead.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the benefits of infrastructure monitoring?
&lt;/h2&gt;

&lt;p&gt;Continuous infrastructure monitoring helps you achieve the desired product performance, maximize efficiency, and save resources by detecting problems before they escalate and impact your business.&lt;/p&gt;

&lt;p&gt;Below are some of the many reasons why you should invest in a reliable monitoring tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Respond to incidents fast
&lt;/h3&gt;

&lt;p&gt;If an incident happens, you should be the first one to know about it. Having a clear view of your infrastructure is crucial if you want to be able to &lt;strong&gt;detect and resolve any problems before they spread and potentially damage your relationship with your users.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Regardless of the nature of the issue you’re facing, being able to respond to it as soon as it appears will go a long way toward &lt;strong&gt;protecting your business.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Get a better understanding of your infrastructure
&lt;/h3&gt;

&lt;p&gt;Monitoring your infrastructure continuously and proactively &lt;strong&gt;gives you a clear picture of how it performs on a daily basis, and allows you to monitor failure patterns and pick up on any warning signs early on.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For instance, if your application suddenly starts to perform below expectations, visualizing the monitoring data might give you valuable insight into what has caused the bottleneck.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Make informed, data-driven decisions
&lt;/h3&gt;

&lt;p&gt;Having clear, data-driven insights into the health of your infrastructure isn’t crucial in just helping you understand its ongoing performance. Most importantly, it allows you to &lt;strong&gt;make informed decisions about your long-term IT infrastructure strategy and investment plans.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Save time and money
&lt;/h3&gt;

&lt;p&gt;If you want to keep your infrastructure-related costs under control, you can’t afford to go without the use of monitoring tools. They offer an easy way to find out how your server plans correspond to your actual needs.&lt;/p&gt;

&lt;p&gt;Whether you’ve been underutilizing your existing cloud service or are about to require a larger and more expensive package, &lt;strong&gt;analyzing your monitoring data will help you manage your budget.&lt;/strong&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  5. Give yourself peace of mind
&lt;/h3&gt;

&lt;p&gt;Monitoring your infrastructure 24/7 simply gives you peace of mind. If anything goes wrong, you will be notified the very same moment and can get down to fixing the problem straight away.&lt;/p&gt;

&lt;p&gt;Analyzing the monitoring data can also provide you with insight on the kind of long-term trends you can expect in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are some of the tools used in infrastructure monitoring?
&lt;/h2&gt;

&lt;p&gt;To get started with infrastructure monitoring, first you need to pick the right tool. Since different systems require different solutions, it’s worth taking a look around to make sure you choose the one with the most suitable features for your set of servers.&lt;/p&gt;

&lt;p&gt;For the purpose of this article, we’ll broadly break them up into two categories: &lt;strong&gt;cloud-native and non-native.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cloud-native solutions
&lt;/h3&gt;

&lt;p&gt;If you use cloud services to host your infrastructure, sticking to your provider’s native solutions is usually the best option.&lt;/p&gt;

&lt;p&gt;The native tools are a breeze to set up, since they come with your cloud account and are easy to maintain. You won’t need to worry about your tool-hosting server or install additional agents on the server for most basic metrics.&lt;/p&gt;

&lt;p&gt;The most popular cloud services and their native monitoring tools are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/"&gt;AWS&lt;/a&gt;: &lt;a href="https://aws.amazon.com/cloudwatch/"&gt;Amazon CloudWatch&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://cloud.google.com/"&gt;Google Cloud Platform&lt;/a&gt;: &lt;a href="http://cloud.google.com/monitoring/"&gt;Stackdriver Monitoring&lt;/a&gt; and &lt;a href="http://cloud.google.com/logging/"&gt;Stackdriver Logging&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://azure.microsoft.com/en-us/"&gt;Azure&lt;/a&gt;: &lt;a href="https://azure.microsoft.com/en-gb/services/monitor/"&gt;Azure Monitor&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools usually provide us with some basic data at the hypervisor level (the tool responsible for server virtualization). However, it’s possible to push custom data using scripts or agents. AWS even &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/mon-scripts.html"&gt;offers one&lt;/a&gt; that monitors RAM and disk usage.&lt;/p&gt;

&lt;p&gt;On top of monitoring, cloud services can also track API calls using CloudTrail. This can provide you with some insight on, for instance, the changes made to the infrastructure, the resources accessed by the users, and others.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Non-native solutions
&lt;/h3&gt;

&lt;p&gt;Besides cloud-native solutions, you can always make use of non-native tools. They’re a good option when you need to monitor on-premise infrastructure.&lt;/p&gt;

&lt;p&gt;Some non-native solutions require additional software (a client) to be installed on each server that needs to be monitored. The data is then sent by the agent to the server (the tool) which subsequently processes the information. Some of the most popular ones include: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://prometheus.io/"&gt;Prometheus&lt;/a&gt; + &lt;a href="https://prometheus.io/docs/alerting/alertmanager/"&gt;Alertmanager&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grafana.com/"&gt;Grafana&lt;/a&gt; (as data visualizer and for triggering alerts)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nagios.org/"&gt;Nagios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zabbix.com/"&gt;Zabbix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://icinga.com/"&gt;Icinga&lt;/a&gt;/&lt;a href="https://icinga.com/docs/icinga2/latest/"&gt;Icinga2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://graphiteapp.org/"&gt;Graphite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sensu.io/"&gt;Sensu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An overview of Amazon CloudWatch and OpsGenie
&lt;/h2&gt;

&lt;p&gt;As you’ve seen above, there are plenty of infrastructure monitoring tools to choose from. However, for the purpose of giving you a general idea of how they work, we will focus on the examples of Amazon CloudWatch and OpsGenie.&lt;/p&gt;

&lt;p&gt;We used these tools for one of our clients who had chosen AWS as a cloud provider for their infrastructure. Although we can’t identify who the client was for this particular project, you can always explore &lt;a href="https://stxnext.com/portfolio/"&gt;our portfolio&lt;/a&gt; for other client stories.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Amazon CloudWatch
&lt;/h3&gt;

&lt;p&gt;Amazon CloudWatch is a native tool to monitor AWS resources, such as EC2, RDS, SQS, ElastiCache, SES, and others. It allows you to create dashboards to visualize metrics, which can include the amount of RAM used by the EC2 instance or the number of connections established to the RDS.&lt;/p&gt;

&lt;p&gt;The Dashboard feature is very useful, as it can give you instant insight into the status of your infrastructure. It auto-refreshes, so you can display it on a TV screen in the developers’ room.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ecPOUc2r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9123th2wx8k4p3hxg2n3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ecPOUc2r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9123th2wx8k4p3hxg2n3.png" alt="Amazon CloudWatch" width="880" height="312"&gt;&lt;/a&gt;&lt;em&gt;A sample dashboard in Cloudwatch&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, the key functionality of CloudWatch is Alarms. It allows you to set up alarms for the metrics you want to monitor. &lt;/p&gt;

&lt;p&gt;Although many of them will indeed have to be client-specific, you should also consider using basic AWS metrics such as the CPU and RAM usage of EC2 instances, Read/Write IOPS for DB instances, and the number of bounced emails from SES.&lt;/p&gt;

&lt;p&gt;Usually, you need to adjust the alarms after the initial setup to avoid false positives. &lt;/p&gt;

&lt;p&gt;An alarm in CloudWatch can have one of these three statuses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OK&lt;/li&gt;
&lt;li&gt;INSUFFICIENT_DATA&lt;/li&gt;
&lt;li&gt;ERROR
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CdniWQr1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eiylp5goyz8b7k2gfim7.png" alt="Alarms in Amazon Cloudwatch" width="880" height="357"&gt;&lt;em&gt;Alarms in Amazon Cloudwatch&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whenever an alarm changes its status, you need to identify what action to take. This leads us to the next tool we want to give you a general overview of: OpsGenie. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. OpsGenie
&lt;/h3&gt;

&lt;p&gt;OpsGenie is an incident management service that integrates with your monitoring tool to provide you with around-the-clock notifications on the status of your infrastructure. It’s triggered by SNS—the AWS messaging service that can send notifications via email, webhook, or text message.&lt;/p&gt;

&lt;p&gt;A tool like OpsGenie plays a crucial role when you want to stay ahead of disruptions and resolve any issues before they escalate. It will help your team build on-call schedules and will keep everyone informed on who’s accountable for any alerts that emerge.&lt;/p&gt;

&lt;p&gt;The platform’s reporting and analytics tools will also help you get to the bottom of the alerts and analyze the team’s workload and performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6T_7ehcr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ij96ngg2wurjzwtngb8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6T_7ehcr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ij96ngg2wurjzwtngb8.png" alt="OpsGenie simple statistics" width="880" height="647"&gt;&lt;/a&gt;&lt;em&gt;OpsGenie simple statistics&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One OpsGenie instance can work for multiple teams, and each team member can look up the schedule, revise it, or just go through past alarms.&lt;/p&gt;

&lt;p&gt;The tool is available as a native app for both Android and iOS. We use it a great deal, because it supports push and email notifications as well as mobile phone calls.&lt;/p&gt;

&lt;p&gt;The app allows you to manage the way you want to be notified about any alerts. For instance, we’ve customized it to receive the first notification as a push notification. If the notification isn’t acknowledged within three minutes, the app will make a phone call to the on-duty engineer. In case the engineer doesn’t act upon it, OpsGenie will escalate the process and alert other team members.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DjooNEEZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3s8d27ja8o2w1mhjymhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DjooNEEZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3s8d27ja8o2w1mhjymhi.png" alt="OpsGenie Alerts panel" width="880" height="320"&gt;&lt;/a&gt;&lt;em&gt;OpsGenie Alerts panel&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloud</category>
      <category>aws</category>
    </item>
    <item>
      <title>How to Audit the Quality of Your Python Code: A Step-by-Step Guide (Checklist Inside)</title>
      <dc:creator>Adam Przewoźny</dc:creator>
      <pubDate>Sun, 06 Mar 2022 19:05:18 +0000</pubDate>
      <link>https://dev.to/stx-next/how-to-audit-the-quality-of-your-python-code-a-step-by-step-guide-checklist-inside-2hap</link>
      <guid>https://dev.to/stx-next/how-to-audit-the-quality-of-your-python-code-a-step-by-step-guide-checklist-inside-2hap</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally written by Maciej Król&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building a software development project is a bit like a game of Jenga.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All elements create one perfect tower. Usually, it might be tweaked and worked on with no consequences. But if it has even one vulnerable place, a wrong move might ruin all the hard work.&lt;/p&gt;

&lt;p&gt;Okay, so it’s not a perfect analogy. A software program requires much more work than a pile of wooden blocks and we don’t necessarily strip it of its parts, but rather add the next ones.&lt;/p&gt;

&lt;p&gt;However, the “poke one and all will fall” metaphor still stands. &lt;strong&gt;If your project has any weak points, they might doom the entire construction.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It doesn’t matter how well written the rest of your code is if that one tool you used is outdated and might cause serious security breaches. And the more sensitive data your product is dealing with, the more careful you have to be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A code audit is vital to ensure your product is of good quality, secure, and ready to launch.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this article, you will find a detailed guide on what a code audit is, why you need it and how to perform it, step by step. &lt;a href="https://stxnext.com/what-is-python-used-for/"&gt;As a Python-centered software house&lt;/a&gt;&lt;/strong&gt;, we decided to focus on how to run an audit of Python-based code. However, you will find some of the tips and guidelines relevant regardless of your technology choice.&lt;/p&gt;

&lt;p&gt;We will also provide you with a checklist and a sample report from an audit so that you can see what a well-prepared, comprehensive auditing process looks like. The exemplary audit is over 20 pages long and will serve as a fantastic point of reference for your future work! &lt;a href="https://stxnext.com/blog/2020/04/23/how-to-audit-the-quality-of-your-python-code/#audit-pdf-download"&gt;Download the checklist and report in PDF format below.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With our guide, you will be able to run a Python code audit yourself, and learn what you should expect from one.&lt;/p&gt;

&lt;p&gt;Read on!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a code audit?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;“Code audit is a comprehensive analysis of source code in a programming project with the intent of discovering bugs, security breaches or violations of programming conventions,”&lt;/strong&gt; according to Wikipedia. I know that quoting Wikipedia in an article is like quoting Merriam-Webster during a wedding speech—but this time they got it so right that they deserve credit!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The intention of every code audit is ensuring that a given program is:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;secure,&lt;/li&gt;
&lt;li&gt;devoid of bugs and defects,&lt;/li&gt;
&lt;li&gt;easy to maintain and be further worked with,&lt;/li&gt;
&lt;li&gt;up to date with the current standards,&lt;/li&gt;
&lt;li&gt;in line with coding best practices. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skip any of these, and you’re sacrificing the quality and security of your code, which may—and most probably will—have disastrous consequences.&lt;/strong&gt; Poor documentation and tech debt might slow down or even halt your project; bugs and security breaches might cost you clients, reputation, and good user ratings. And that’s just the start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With a code audit, you’ll be sure your code is secure, bug-free and ready for handover.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Code audit vs. code review
&lt;/h3&gt;

&lt;p&gt;After reading the section above, you might think: okay, but everything you’ve just described can be achieved with the help of a code review, and we run these regularly!&lt;/p&gt;

&lt;p&gt;It’s true that the terms might sometimes be used interchangeably, but there are a few subtle differences between them. &lt;/p&gt;

&lt;p&gt;Code review is contained within one team—the developers review each other's code, and they focus only on one specific part.&lt;/p&gt;

&lt;p&gt;A code audit, on the other hand, always concerns the whole project and is performed by a person outside of the team—be it other developers, or even an outside company.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;While code reviews are useful and necessary, performing a code audit every once in a while makes a tremendous difference.&lt;/strong&gt; Let me use another metaphor here: reviews are like checking different parts of your car for potential malfunctions. Of course, it’s necessary to see if the headlights operate correctly, if both wipers are fine, and if your brakes do their job… But unless you start the car, take a drive, and assess how everything works together, you won’t know how good the whole machine actually is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As the unwritten rule goes, the more people see your code, the better.&lt;/strong&gt; And the more you fix, the more faultlessly the project will perform in the long run.&lt;/p&gt;

&lt;h2&gt;
  
  
  When can you benefit from a code audit?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You might find yourself in need of running a code audit on many different stages of development and different situations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Before introducing your product to the market,&lt;/strong&gt; to make extra sure the quality is impeccable and you won’t wake up the next day seeing a bunch of one-star reviews;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;After inheriting legacy code,&lt;/strong&gt; to help you plan your future work and assess the scope, cost and time-frame of the project;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Before you invest in a project,&lt;/strong&gt; to verify whether it’s a good bet;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Whenever you feel your product is suboptimal.&lt;/strong&gt; Perhaps the app’s lagging, or there are a few too many bugs to ignore? It’s never too late to check the code and apply changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The benefits of a code audit
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A code audit serves many different purposes. They all depend on where you stand.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From a developers’ point of view, you get the following advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;As mentioned above, &lt;strong&gt;the more people see your code, the better.&lt;/strong&gt; If your product has undergone a comprehensive check-up, chances are any potential bugs and vulnerabilities will be found pre-release and you can fix them stress-free. Not to mention it will help you sleep soundly knowing that all the tools are up to date and following the maximum security protocol.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It’s extremely rare that the very same team of developers works on the same product from start to finish.&lt;/strong&gt; Coworkers might change, sometimes an outsourced team or two might join the efforts, and the total number of developers might be scaled up or down. Additionally, every part of the source code is written by different people with different skills and competences.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s why it’s advisable to perform an audit each time you get source code that you haven’t worked with before (for example, we usually run an internal audit on the code we receive from a client before we start working on it). It will help you assess the scope of your work, the general quality, and maintainability.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An audit will help you avoid technical debt.&lt;/strong&gt; Trust me, “that’s a problem for future me” is not a good approach when it comes to software development.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;As a team leader, you’ll find that:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performing a code audit yourself or at least participating in it will give you an overview of the whole project.&lt;/strong&gt; Usually, team leaders don’t see the code on a daily basis, so an audit will help them get acquainted with the present state of the project, its structure, and its functionalities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;And from a strictly business perspective, you get the following advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;An audit helps prove that your program is ready to be launched and introduced to your clients and customers.&lt;/strong&gt; Malfunctions or security breaches might potentially cost you a lot of money—and your reputation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;An up-to-date, fresh and technologically relevant project is more attractive for developers.&lt;/strong&gt; High-quality code will attract high-quality talents!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Audited code helps simplify and streamline the development process,&lt;/strong&gt; which in turn means work can progress faster with fewer blockers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Python code audit—step-by-step guide + checklist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;In this section, we will introduce a step-by-step process of how to run a Python code audit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each subsection details the crucial elements of the code audit. It will give you an idea of how to structure the document. &lt;/p&gt;

&lt;p&gt;We also included tips on how to ensure you follow the best possible practices from the very beginning. You can apply them even before the audit!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To see what the end result should look like, consult our example provided in the free PDF below. It’s over 20 pages long and based on a real-life code audit we performed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Code repository
&lt;/h3&gt;

&lt;p&gt;In the beginning, &lt;strong&gt;it’s important to check for a version control system that tracks and provides changes to the source&lt;/strong&gt; (like GIT, for example). Verify if it’s well-maintained.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TIP:&lt;/strong&gt; Consider working according to the &lt;a href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow"&gt;Gitflow Workflow&lt;/a&gt;, which “dictates what kind of branches to set up and how to merge them together.” Pay attention to the right names of the branches. If your product is particularly vast, consider using appropriate &lt;a href="https://developer.github.com/v3/git/tags/"&gt;Git tags&lt;/a&gt;. It makes managing a larger project infinitely easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Software architecture
&lt;/h3&gt;

&lt;h4&gt;
  
  
  a) Technology choices
&lt;/h4&gt;

&lt;p&gt;The point of this section is to verify if the tech stack is the optimal choice for the project and if it’s internally compatible. &lt;/p&gt;

&lt;p&gt;When you start verifying the technology choices, &lt;strong&gt;the first step should be to check if all applications used are named according to the LTS version and if they are up-to-date.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then, it’s time to judge if all the components are &lt;a href="https://www.stxnext.com/stx-new-blog/how-can-your-software-benefit-automated-testing/"&gt;well-tested&lt;/a&gt; and if they fit each other.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What does it mean in practice? For example, &lt;a href="https://www.stxnext.com/stx-new-blog/how-can-your-software-benefit-automated-testing/"&gt;Django&lt;/a&gt; apps &lt;a href="https://stackoverflow.com/questions/9540154/which-database-engine-to-choose-for-django-app/9540312"&gt;go together with Postgres&lt;/a&gt; much more often than with other database engines, like MySQL. While the less popular choices are not necessarily technologically weaker, opting for them will drastically reduce your opportunities to find help with any potential problems.&lt;/p&gt;

&lt;p&gt;Such aspects are important to be taken into account in order to assess the sustainability of the project.&lt;/p&gt;

&lt;h4&gt;
  
  
  b) Deployment configuration
&lt;/h4&gt;

&lt;p&gt;It’s always worth checking &lt;strong&gt;which services are used to support the application.&lt;/strong&gt; You should pay attention to the software providing hosting services (uwsgi, gunicorn, nginx) and the hosting method (whether it’s cloud or local). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TIP:&lt;/strong&gt; There is no clear answer which methods are right—each hosting type has its advantages and disadvantages. Everything depends on the type of project you’re working with.&lt;/p&gt;

&lt;p&gt;However, I sincerely recommend cloud hosting. It will not only help you save money (no need to care about the hardware, less maintenance, increased productivity), but you also gain much higher availability of the app. Most cloud providers offer over &lt;a href="https://kinsta.com/blog/google-cloud-vs-aws/#uptime"&gt;99,99%!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The next step is to verify whether the application contains files which are responsible for the virtualization of the project.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TIP:&lt;/strong&gt; I highly advise using &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt;. It allows solving a lot of potential problems and bugs during the development stage, as the development version functions in an environment identical to the product version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then, it’s time to check whether the README file contains all the necessary elements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;instructions for configuration,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;instructions for installation,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a user’s manual,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a manifest file (with an attached list of files),&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;information on copyrights and licenses,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;contact details for the distributors and developers,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;known bugs and malfunctions,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;problem solving section,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a changelog (for developers).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While revising your project catalog, &lt;strong&gt;you should check if it includes files responsible for continuous integration and deployment (CI/CD).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TIP:&lt;/strong&gt; Well-constructed CI/CD pipelines can greatly benefit your project. They allow for a more effective way of building the program, but they also include scripts responsible for testing the application and verifying its validity during code-building.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check the project configuration and verify if it doesn’t contain any passwords that a third person could find.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TIP:&lt;/strong&gt; It’s advisable to keep all logins and passwords necessary to run the application in environment variables—whether in a machine on which the application runs or in the tool responsible for CI/CD. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check if there’s an Error Tracking System in place.&lt;/strong&gt; One of the most popular ones is &lt;a href="https://sentry.io/welcome/"&gt;Sentry&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Coding best practices
&lt;/h3&gt;

&lt;p&gt;This section will look differently depending on the programming language and the packages/libs you use. &lt;/p&gt;

&lt;p&gt;With Python, &lt;strong&gt;you need to check carefully whether the code is compliant with the PEP 8 style guide and the PEP 257 docstring conventions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The good news is, you don’t have to do it all manually. There are tools that might help you along the way.&lt;/p&gt;

&lt;h4&gt;
  
  
  a) Linters
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pylama.readthedocs.io/en/latest/"&gt;Pylama&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://flake8.pycqa.org/en/latest/"&gt;Flake8&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  b) Other standalone tools
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.pylint.org/"&gt;Pylint&lt;/a&gt;—a source code, bug and quality checker for Python;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pypi.org/project/pyflakes/"&gt;PyFlakes&lt;/a&gt;—another bug checker (it only checks for logical errors, not for style, but it works faster);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pypi.org/project/pycodestyle/"&gt;Pycodestyle&lt;/a&gt;—checks Python code against the style conventions in PEP 8;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pypi.org/project/pydocstyle/"&gt;Pydocstyle&lt;/a&gt;—checks compliance with Python docstring conventions;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pypi.org/project/bandit/"&gt;Bandit&lt;/a&gt;—finds common security issues in Python code;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://mypy-lang.org/"&gt;MyPy&lt;/a&gt;—static type checker for Python.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  c) Code analysis and formatting tools
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/PyCQA/mccabe"&gt;Mccabe&lt;/a&gt;—a Python complexity checker;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pypi.org/project/radon/"&gt;Radon&lt;/a&gt;—a Python tool that computes various metrics from the source code;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/psf/black"&gt;Black&lt;/a&gt;—a Python code formatter;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/timothycrosley/isort"&gt;Isort&lt;/a&gt;—a Python utility/library to sort imports;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/google/yapf"&gt;Yapf&lt;/a&gt;—a Python formatter.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even though the tools can greatly automate and speed up your work, &lt;strong&gt;it’s still worth it to analyze the code manually in order to find any potential:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;bugs,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bottlenecks,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;performance issues,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;security vulnerabilities,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dangers connected with maintaining the application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Tips for the future: how to ensure the quality of your code
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Code audits can help improve your code and get rid of any existing issues.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But if upon running the code audit the list of things to improve feels too long, &lt;strong&gt;try getting familiar with a few good practices.&lt;/strong&gt; While not all of them may be applied in every single team, here are a few that are worth taking into consideration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Every piece of code should be reviewed by at least two developers;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use githooks;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decide on one specific formatter configuration for the whole team;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Share your knowledge! Both when it comes to technologies that you are proficient in and when it comes to tasks that you solved—it helps the team to adopt the same good practices;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider asking the team members to use the same code editor—it will help with standardization.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;We hope our guide on how to run a code audit will help you perform one on your own, or assess what a good audit document should look like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to get to work, we recommend you &lt;a href="https://www.stxnext.com/code-audit-checklist-sample-report"&gt;download our PDF&lt;/a&gt;—it consists of a checklist and a real-life audit example for reference.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And if you want to find out more about how to ensure the better quality of your code, why not check out the following articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.stxnext.com/stx-new-blog/moderated-unmoderated-remote-usability-testing/"&gt;Moderated and Unmoderated Remote Usability Testing: What Is It, How to Run It, and What Are the Benefits?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.stxnext.com/stx-new-blog/what-is-devops/"&gt;What Is DevOps? An Introduction for Development Managers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.stxnext.com/stx-new-blog/how-can-your-software-benefit-automated-testing/"&gt;How Can Your Software Benefit from Automated Testing?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>qa</category>
    </item>
  </channel>
</rss>
