<?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: Natalia D</title>
    <description>The latest articles on DEV Community by Natalia D (@whatever).</description>
    <link>https://dev.to/whatever</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F101947%2F630bca2d-e3d7-4f4a-b755-d7fffe1c7661.jpg</url>
      <title>DEV Community: Natalia D</title>
      <link>https://dev.to/whatever</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/whatever"/>
    <language>en</language>
    <item>
      <title>What is Quantum Computer: explained in 5 mins</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Mon, 21 Aug 2023 17:28:14 +0000</pubDate>
      <link>https://dev.to/whatever/wtf-is-quantum-computer-explained-in-5-mins-404c</link>
      <guid>https://dev.to/whatever/wtf-is-quantum-computer-explained-in-5-mins-404c</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2F5givm1fg1v23n8kjn8c2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F5givm1fg1v23n8kjn8c2.jpg" alt="Image description" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Quantum computers already exist&lt;/li&gt;
&lt;li&gt;Quantum Physics 101&lt;/li&gt;
&lt;li&gt;Quantum Computer is run on qubits&lt;/li&gt;
&lt;li&gt;Quantum Computing&lt;/li&gt;
&lt;li&gt;How Quantum Computer can solve RSA?&lt;/li&gt;
&lt;li&gt;What are Quantum Computers good for?&lt;/li&gt;
&lt;li&gt;Links&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Quantum computers already exist
&lt;/h2&gt;

&lt;p&gt;If we think that classical computer is a car, then Quantum Computer is not a faster car, it's a boat. It is meant for other tasks [1]. &lt;/p&gt;

&lt;p&gt;Several Quantum Computers already exist (e.g. China, Google, IBM). Some quantum computers can work only when cooled down to almost absolute zero, other work given the room temperature, but have huge size. It's not clear yet which implementation will win [2].&lt;/p&gt;

&lt;h2&gt;
  
  
  Quantum Physics 101
&lt;/h2&gt;

&lt;p&gt;Particles (electrons, etc) are not tiny little balls of stuff [3]. That works for lots of thought experiments, but in fact they are superbizarre little fluctuations in fields that permeate the entire universe.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Here is my own understanding. Particles can be like waves in the water, but when you catch them to perform measurements, for a glimpse of time they turn into a little ball with some labels. When you set them free, they are waves again. They are like some magical shapeshifters.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F8aj8vln0vwpcmzp7m772.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8aj8vln0vwpcmzp7m772.jpg" alt="Image description" width="581" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quantum Computer is run on qubits
&lt;/h2&gt;

&lt;p&gt;Qubits are like waves. A qubit could really likely to be 0 which means a lower energy wave. A qubit could be more likely to be 1 which means a higher energy wave [1]. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fqnmuagbcg834o5ako5cx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqnmuagbcg834o5ako5cx.jpg" alt="Image description" width="414" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each qubit has a probability of being each. When a quantum computer is working, the probabilities of multiple qubits interact. They add constructively or desctructively. &lt;/p&gt;

&lt;p&gt;What is the job of software engineer here? She/he will alter the probabilities while the algorithm is running. Quantum computers don't try all the options. A Quantum Computer more like watches the pond, how the wave interacts, and then helps to find the most likely answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quantum Computing
&lt;/h2&gt;

&lt;p&gt;Mathematically [4], a qubit is a linear combination (a chance being 0 + a chance being a 1):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F6q38ksbmztpp61azisf2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F6q38ksbmztpp61azisf2.jpg" alt="Image description" width="102" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similar to classical computers, specialists string together qubits, using construct called gates that can alter the states of qubits into circuits. E.g. we can have a qubit that's at the state of 0. We can use Hadamard gate to put it into superposition between 0 and 1. We can have multiple qubits with multiple gates in a circuit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ftse9i4xrwy8jqil0b9tw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftse9i4xrwy8jqil0b9tw.jpg" alt="Image description" width="215" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the circuit to be useful, at some point you need to read about its outputs = measure it. When a qubit is measured, it loses its superposition and collapses into just a simple 0 or 1. To make sure the collapsed answer we got is a correct one, quantum gates need to be arranged in a way so that it would amplify the correct answer and cancel all the incorrect ones. This process is called interference. &lt;/p&gt;

&lt;p&gt;We can also entangle two qubits so that their states have 50% chance of measuring 00 and 50% of measuring 11, but never a 01 or a 10.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Quantum Computer can solve RSA?
&lt;/h2&gt;

&lt;p&gt;RSA algorithm depends on the difficulty of finding factors of a very large number. Here is an example of factors: for 15 it's 3 and 5, because they are both primes and 3x5 = 15. It's easy to find the factors of 15 by trial and error, but the difficulty grows exponentially as the size of the number increases.&lt;/p&gt;

&lt;p&gt;Peter Shor from Bell labs came up with an algorithm, its main idea is that long strings of numbers contain periodicities - patterns of repetition - which may not be obvious at first sight but may be teased out by mathematical analysis. Periodic patterns can be probed using Fourier analysis, which unpacks complicated wave patterns into their component parts. E.g. the complicated sound wave corresponding to the sound of a group of a musical instruments playing a chord together could be unravelled by Fourier analysis into a wave corresponding to a violin note, or to the cello, etc. A quantum computer using Shor's algorithm could set up a superposition with all the possible periods (waves), and select the one that actually fitted number in question. The periodicity found could then be used by a classical computer to reveal the factors of that number. &lt;/p&gt;

&lt;h2&gt;
  
  
  What are Quantum Computers good for?
&lt;/h2&gt;

&lt;p&gt;They are good for finding structure in tons of data [1]. &lt;em&gt;As for me, I expect that they will at least help to advance ML (especially not-supervised or semi-supervised learning).&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=e3fz3dqhN44" rel="noopener noreferrer"&gt;Cleo Abram. Quantum Computers, explained with MKBHD. Youtube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=_OjRClPzU6Y" rel="noopener noreferrer"&gt;Michi Kaku | Quantum Supremacy | Talks at Google. Youtube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Jorge Cham &amp;amp; Daniel Whiteson. We Have No Idea. A Guide to the Unknown Universe. &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=lt4OsgmUTGI" rel="noopener noreferrer"&gt;What is Quantum Computing? IBM Technology. Youtube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;John Gribbin. Computing with Quantum Cats. From Alan Turing to teleportation&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>quantumcomputing</category>
      <category>quantum</category>
      <category>qubits</category>
      <category>cryptography</category>
    </item>
    <item>
      <title>A/B testing: should you use it?</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Sat, 19 Aug 2023 17:15:38 +0000</pubDate>
      <link>https://dev.to/whatever/ab-testing-should-you-use-it-1f4g</link>
      <guid>https://dev.to/whatever/ab-testing-should-you-use-it-1f4g</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2Foyku8qbrm1k5jlxlz61s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Foyku8qbrm1k5jlxlz61s.jpg" alt="Image description" width="555" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you decided to read this post, I hope you know what an A/B test is. Probably you either work at a startup or at some Big Company with thousands of users.&lt;/p&gt;

&lt;p&gt;If you work at a Big Company, you just have to go with the company flow and do the A/B testing. Here are two things that might be useful for you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The famous &lt;a href="https://www.evanmiller.org/ab-testing/sample-size.html" rel="noopener noreferrer"&gt;Sample Size Calculator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Look at your KPIs and think about whether you can afford to &lt;a href="https://growrevenue.io/trivial-vs-radical-ab-testing/" rel="noopener noreferrer"&gt;test something more interesting&lt;/a&gt; than the button colours.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you work for a startup, probably you don't have much traffic. Also the majority of traffic doesn't correspond to real people...So A/B testing doesn't make much sense. In my opinion, the best option in this case would be catch some people in the hall and make videos how they use different versions of your website or app. Try to make the videos that would capture not only what's happening on the screen, but also record user's face and what he/she is saying while working with your product. When you rewatch these videos, there will be a lot of interesting discoveries!&lt;/p&gt;

</description>
      <category>abtesting</category>
      <category>abtest</category>
    </item>
    <item>
      <title>What happens when you type a URL into your browser?</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Sat, 22 Apr 2023 09:39:44 +0000</pubDate>
      <link>https://dev.to/whatever/what-happens-when-you-type-a-url-into-your-browser-23o3</link>
      <guid>https://dev.to/whatever/what-happens-when-you-type-a-url-into-your-browser-23o3</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2Fmzdobrdzcyf6456r4xk1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmzdobrdzcyf6456r4xk1.jpeg" alt="Image description" width="256" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From my experience, if you are a &lt;em&gt;frontend dev&lt;/em&gt; being &lt;em&gt;interviewed by&lt;/em&gt; a &lt;em&gt;backend&lt;/em&gt; dev, which often happens when you plan to join a small company, there is quite high chance that you'll have to answer these two questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what happens when you type a URL into your browser&lt;/li&gt;
&lt;li&gt;describe security attacks that you know.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not so long ago I had to refresh my notes about it, and I would like to share them with you. So,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens when you type a URL into your browser?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'll omit the basics that people usually remember and focus only on things that I usually have to re-read&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  TOC
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Browser looks up IP address for the domain&lt;/li&gt;
&lt;li&gt;User initiates communication (Application layer)&lt;/li&gt;
&lt;li&gt;Data encapsulation begins (Transport layer)&lt;/li&gt;
&lt;li&gt;Data is sent (Network layer)&lt;/li&gt;
&lt;li&gt;Link layer, Physical layer&lt;/li&gt;
&lt;li&gt;Data arrives at the server&lt;/li&gt;
&lt;li&gt;Extra details you might want to know&lt;/li&gt;
&lt;li&gt;The links I used&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Browser looks up IP address for the domain&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Each device on the internet has a unique IP address. An IP address contains 4 numbered parts, e.g. 203.0.113.0. When you're loading a webpage from a domain your browser has never visited before, your browser may need to make a DNS request to resolve IP address, associated with the domain name. This stack of protocols is used when a DNS request is sent through the Internet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Far9zzswuwpmgwxcwas3o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Far9zzswuwpmgwxcwas3o.jpg" alt="Image description" width="287" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fm5tfy3avfjdzukzqekov.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fm5tfy3avfjdzukzqekov.jpg" alt="Image description" width="300" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then your browser will make an HTTPS request to fetch the webpage. This protocol stack is used when an HTTP request is sent through the Internet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fp35ik42ff1zssr6bun3i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fp35ik42ff1zssr6bun3i.jpg" alt="Image description" width="288" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nobody wants to do DNS requests too often, so different kinds of cache exist: &lt;strong&gt;browser cache, OS cache, router cache, ISP (Internet Service Provider) cache&lt;/strong&gt;. If the browser cannot find the IP address at any of those cache layers, the DNS server on your corporate network or at your ISP does a recursive DNS lookup. A recursive DNS lookup asks multiple DNS servers around the Internet, which in turn ask more DNS servers for the DNS record until it is found.&lt;/p&gt;

&lt;h3&gt;
  
  
  User initiates communication (Application layer)&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A user on one host sends a message or issues a command that must access a remote host. The application protocol associated with the command or message formats the packet so that it can be handled by the appropriate transport layer protocol, TCP or UDP. Besides HTTPS, there are thousands of other application-layer protocols: SMTP, IMAP, and POP3 for email; XMPP, IRC, ICQ for chat; Telnet, SSH, RDP for remote administration; etc.&lt;/p&gt;

&lt;p&gt;When the data contains private information, it needs to be transported securely from the sender to the destination. The Transport Layer Security (TLS) protocol uses algorithms to encrypt the data, while certificate authorities help users trust the encryption.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fejin2kxh44udna8nsst0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fejin2kxh44udna8nsst0.jpg" alt="Image description" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a user connects to a webpage, the webpage will send over its SSL certificate which contains the public key necessary to start the secure session. The two computers, the client and the server, then go through a process called a SSL/TLS handshake.&lt;/p&gt;

&lt;p&gt;Many website hosting providers and other services will offer TLS/SSL certificates for a fee. These certificates will often be shared amongst many customers. More expensive certificates are available which can be individually registered to particular web properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data encapsulation begins (Transport layer)&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Data needs to be broken up into small packets, which are then reassembled at the destination. Two main transport protocols are &lt;em&gt;TCP&lt;/em&gt; and &lt;em&gt;UDP&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If &lt;em&gt;TCP&lt;/em&gt; determines that IP packets are lost, duplicated, or out of sequence, it’ll request retransmission of missed data, correct out-of-order data. &lt;em&gt;UDP&lt;/em&gt; offers no guarantees of delivery, ordering, or duplicate protection. Its lack of retransmission delays makes it suitable for real-time applications such as Voice over IP (VoIP), online games, live video streaming, video conferencing. All of these require transferring data as fast as possible, even if it results in a glitch or two. Knowing that &lt;em&gt;TCP&lt;/em&gt; is primarily for functions where accuracy is prioritized over timeliness, this protocol is common for Internet essentials like sending emails, sharing files, text messaging and accessing web pages.&lt;/p&gt;

&lt;p&gt;Both &lt;em&gt;TCP&lt;/em&gt; and &lt;em&gt;UDP&lt;/em&gt; divide the data received from the application layer into segments and attach a header to each segment. Both &lt;em&gt;TCP&lt;/em&gt; and &lt;em&gt;UDP&lt;/em&gt; headers contain the sending and receiving ports and checksum. The checksum data is used to determine whether data has transferred without error. &lt;em&gt;TCP&lt;/em&gt; headers also include segment ordering information (&lt;em&gt;don't try to memorise this table, it's just for illustrative purposes&lt;/em&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fnndo9nqged62gbdrtkzo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fnndo9nqged62gbdrtkzo.png" alt="Image description" width="714" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When &lt;em&gt;TCP&lt;/em&gt; wants to establish connection, it sends a segment called a SYN to the peer &lt;em&gt;TCP&lt;/em&gt; protocol running on the receiving host. The receiving &lt;em&gt;TCP&lt;/em&gt; returns a segment called an ACK to acknowledge the successful receipt of the segment. The sending &lt;em&gt;TCP&lt;/em&gt; sends another ACK segment, then proceeds to send the data. This exchange of control information is referred to as a three-way handshake. &lt;em&gt;UDP&lt;/em&gt; does not use the three-way handshake.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data is sent (Network layer)&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In the majority of cases, this is dominated by Internet Protocol (IP). The Internet Protocol (IP) is the protocol that describes how to route messages from one computer to another computer on the network. Each message is split up into packets, and the packets hop from router to router on the way to their destination.&lt;/p&gt;

&lt;p&gt;Computers send the first packet to the nearest router. You probably have a router in your home right now, and that's the first stop for your current computer's packets. When the router receives a packet, it looks at its IP header. The most important field is the destination IP address, which tells the router where the packet wants to end up.&lt;/p&gt;

&lt;p&gt;The router has multiple paths it could send a packet along, and its goal is to send the packet to a router that's closer to its final destination. How does it decide? The router has a forwarding table that helps it pick the next path based on the destination IP address. That table does not have a row for every possible IP address; there are too many of them. Instead, the table has rows for IP address prefixes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fh8zm7m4du05d1eourvqf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fh8zm7m4du05d1eourvqf.jpg" alt="Image description" width="252" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;IP addresses are hierarchical. When two IP addresses start with the same prefix, that often means they're on the same large network. Router forwarding tables take advantage of that fact so that they can store far less information. &lt;/p&gt;

&lt;p&gt;Once the router locates the most specific row in the table for the destination IP address, it sends the packet along that path. If all goes well, the packet should eventually arrive at a router that knows exactly where to send it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Link layer, Physical layer&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Ok, but who transmits the bits? To do that work, The network layer logic in a host or router must hand off the packet to the data link layer protocols, which, in turn, ask the physical layer to actually send the data. &lt;/p&gt;

&lt;p&gt;Data-link layer protocols are classified as LAN protocols, WAN protocols, or protocols that can be used for both LANs and WANs. LANs connect devices within a limited area, such as an office, while WANs connect devices that are spread across a large area, such as an entire country or even the world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data arrives at the server&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;On the opposite side of the communication channel is the server, which serves the document as requested by the client. A server appears as only a single machine virtually; but it may actually be a collection of servers sharing the load (load balancing), or a complex piece of software interrogating other computers (like cache, a DB server, or e-commerce servers), totally or partially generating the document on demand.&lt;/p&gt;

&lt;p&gt;A server is not necessarily a single machine, but several server software instances can be hosted on the same machine. &lt;/p&gt;

&lt;p&gt;But how a remote computer can communicate with a program running on your computer? There are not enough IP addresses for that. So people came up with an idea of "ports". Basically, port is a number in a range from 0 to 65535, associated with a specific process or service. An app can open a port - to broadcast a message like if "a message comes for port 5190, it's for me".  &lt;/p&gt;

&lt;p&gt;Ports are software-based and managed by a computer's operating system. During data transfer, only a transport protocol such as TCP or UDP can indicate which port a packet should go to. TCP and UDP headers have a section for indicating port numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extra details you might want to know&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;IP addresses&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One way to find out your computer's IP address is by searching Google for "IP address". Google knows your IP address, since your computer sends a message to the Google computers as soon as it loads google.com.&lt;/p&gt;

&lt;p&gt;Your IP address might be different tomorrow than it is today. Each ISP has a range of addresses they can assign, and they might give you a different one of those addresses each time they see your computer pop up on the network. That's called a dynamic IP address.&lt;/p&gt;

&lt;p&gt;Switching to a different Wi-Fi network will definitely give you a new IP address, since each Wi-Fi provider has its own range of addresses that it can give out. Computers that act as servers, like the computers that power Google.com, often have static IP addresses. That makes it easier for computers to quickly send search requests to the Google servers.&lt;/p&gt;

&lt;p&gt;There are actually two versions of the Internet Protocol in use today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IPv4, the first version ever used on the Internet&lt;/li&gt;
&lt;li&gt;IPv6, a backwards-compatible successor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Back when the Internet protocols were first invented, the creators didn't anticipate how popular it would become and that there would eventually be so many devices wanting to connect to the Internet. When it became obvious in the 1990s that the IPv4 addresses were running out, the IPv6 protocol was proposed with a much longer addressing scheme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;MAC addresses&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A MAC address and an IP address each identify network devices, but they do the job at different levels. MAC address is assigned by the manufacturer of the hardware interface, while the IP address is assigned by the network administrator or Internet Service Provider (ISP). &lt;/p&gt;

&lt;p&gt;The MAC address identifies the device locally, while the IP address identifies it globally. The MAC address is only relevant to the Local Area Network (LAN) to which it's connected and isn't part of the data stream when the packets leave the device's network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Proxies&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Between the Web browser and the server, numerous computers and machines relay the HTTP messages. Those operating at the application layers are generally called proxies. These can be transparent, forwarding on the requests they receive without altering them in any way, or non-transparent, in which case they will change the request in some way before passing it along to the server. Proxies may perform numerous functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;caching (the cache can be public or private, like the browser cache)&lt;/li&gt;
&lt;li&gt;filtering (like an antivirus scan or parental controls)&lt;/li&gt;
&lt;li&gt;load balancing (to allow multiple servers to serve different requests)&lt;/li&gt;
&lt;li&gt;authentication (to control access to different resources)&lt;/li&gt;
&lt;li&gt;logging (allowing the storage of historical information)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Ports and Firewalls&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some attackers try to send malicious traffic to random ports in the hopes that those ports have been left "open," meaning they are able to receive traffic. This action is somewhat like a car thief walking down the street and trying the doors of parked vehicles, hoping one of them is unlocked. &lt;/p&gt;

&lt;p&gt;A firewall is a security system that blocks or allows network traffic based on a set of security rules. Firewalls usually sit between a trusted network and an untrusted network; often the untrusted network is the Internet.&lt;/p&gt;

&lt;p&gt;Properly configured firewalls block traffic to all ports by default except for a few predetermined ports known to be in common use. For instance, a corporate firewall could only leave open ports 25 (email), 80 (web traffic), 443 (web traffic), and a few others, allowing internal employees to use these essential services, then block the rest of the 65,000+ ports.&lt;/p&gt;




&lt;p&gt;If you are still reading, I'll talk about security and encryption in another post. This one got too lengthy to digest already!&lt;/p&gt;

&lt;h3&gt;
  
  
  The links I used&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.cloudflare.com/en-gb/learning/network-layer/what-is-a-computer-port/" rel="noopener noreferrer"&gt;cloudflare&lt;/a&gt;, &lt;a href="https://docs.oracle.com/cd/E19455-01/806-0916/ipov-32/index.html" rel="noopener noreferrer"&gt;oracle&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview" rel="noopener noreferrer"&gt;mozilla&lt;/a&gt;, &lt;a href="https://hypertecsp.com/knowledge-base/the-difference-between-lan-wan-in-wireless-routers/#:~:text=When%20it%20comes%20to%20setting,country%20or%20even%20the%20world." rel="noopener noreferrer"&gt;hypertecsp&lt;/a&gt;, &lt;a href="https://www.sciencedirect.com/topics/engineering/data-link-layer" rel="noopener noreferrer"&gt;sciencefirect&lt;/a&gt;, &lt;a href="https://www.guru99.com/difference-between-mac-address-and-ip-address.html" rel="noopener noreferrer"&gt;guru99&lt;/a&gt;, &lt;a href="https://www.simplilearn.com/what-is-mac-address-how-to-find-it-article" rel="noopener noreferrer"&gt;simplilearn&lt;/a&gt;, &lt;a href="https://www.wowza.com/blog/udp-vs-tcp" rel="noopener noreferrer"&gt;wowza&lt;/a&gt;, &lt;a href="https://www.imperva.com/learn/ddos/tcp-transmission-control-protocol/" rel="noopener noreferrer"&gt;imperva&lt;/a&gt;, &lt;a href="https://www.quora.com/What-are-the-protocols-that-are-built-on-the-TCP-and-the-UDP" rel="noopener noreferrer"&gt;quora&lt;/a&gt;, &lt;a href="https://aws.amazon.com/blogs/mobile/what-happens-when-you-type-a-url-into-your-browser/#:~:text=for%20the%20domain-,Browser%20initiates%20TCP%20connection%20with%20the%20server,Browser%20renders%20the%20content" rel="noopener noreferrer"&gt;aws&lt;/a&gt;, &lt;a href="https://trueconf.com/blog/reviews-comparisons/tcp-vs-udp.html" rel="noopener noreferrer"&gt;trueconf&lt;/a&gt;, &lt;a href="https://www.khanacademy.org/computing/computers-and-internet/xcae6f4a7ff015e7d:the-internet/xcae6f4a7ff015e7d:the-internet-protocol-suite/a/the-internet-protocols" rel="noopener noreferrer"&gt;khanacademy - internet protocols&lt;/a&gt;, &lt;a href="https://www.khanacademy.org/computing/computers-and-internet/xcae6f4a7ff015e7d:the-internet/xcae6f4a7ff015e7d:addressing-the-internet/a/ip-v4-v6-addresses" rel="noopener noreferrer"&gt;khanacademy - ip-v4-v6-addresses&lt;/a&gt;&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>interviewprep</category>
      <category>webdev</category>
    </item>
    <item>
      <title>My thoughts about mentoring junior developers</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Fri, 03 Mar 2023 10:17:45 +0000</pubDate>
      <link>https://dev.to/whatever/my-thoughts-about-mentoring-junior-developers-22bd</link>
      <guid>https://dev.to/whatever/my-thoughts-about-mentoring-junior-developers-22bd</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2F6qw80gbg3fhnc5v45anv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F6qw80gbg3fhnc5v45anv.jpg" alt="Image description" width="288" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While I haven't personally mentored anyone into a mid-level developer, I've had the opportunity to work at various companies and observe both successful and unsuccessful mentoring approaches. These experiences have given me valuable insights that I want to share with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ticket size &amp;amp; watching deadlines
&lt;/h2&gt;

&lt;p&gt;In a perfect world, every ticket would be designed in a way that a mid-level developer could complete it within three days. However, in reality, refinement meetings are often necessary to clarify the scope and requirements of a ticket. It's not uncommon for developers to encounter unexpected challenges when they start working on a ticket.&lt;/p&gt;

&lt;p&gt;It's important to teach junior dev &lt;strong&gt;not to take a ticket for granted&lt;/strong&gt; and to thoroughly evaluate its worth before starting work on it. Here are some key things to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the ticket worth doing at all? Sometimes, there may be a misunderstanding or miscommunication, and the ticket may not actually need to be completed. Sometimes devs just need to update the docs or operation management can change the business process.&lt;/li&gt;
&lt;li&gt;Is the ticket a duplicate of an existing issue? &lt;/li&gt;
&lt;li&gt;Does the ticket have the correct label? A ticket labeled as "frontend" may actually involve backend work and not have other related to it tickets labeled "backend".&lt;/li&gt;
&lt;li&gt;Is the suggested UX good enough? As a developer, you may have ideas for how to improve the user experience or implement the feature more efficiently. &lt;/li&gt;
&lt;li&gt;Are there any other clarifications needed? Sometimes, additional information may be required from the client, devops, or another team member. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For junior developers, it's important to know &lt;strong&gt;when to seek help&lt;/strong&gt; and when to try to solve a problem independently. In order to strike this balance effectively, I would recommend a few key strategies.&lt;/p&gt;

&lt;p&gt;First, if a junior developer is facing a problem they can't resolve on their own, they should leave a "question comment" on the relevant ticket or bring it up in a common chat. This can help ensure that others on the team are aware of the issue and can offer assistance if needed.&lt;/p&gt;

&lt;p&gt;However, it's also important for junior developers to try to solve the problem independently before asking for help. A good rule of thumb is to spend at least &lt;strong&gt;two hours&lt;/strong&gt; working on the problem before seeking assistance. This can help ensure that the developer has thoroughly explored all possible solutions and is not simply relying on others to solve the problem for them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Daily standups&lt;/strong&gt; can also be a valuable opportunity for developers to &lt;strong&gt;discuss any challenges&lt;/strong&gt; they may be facing and seek input from their peers. If a senior developer feels that a junior developer is facing a challenge that may be too difficult for them to handle quickly enough, they may suggest a pair programming call with screen sharing. In addition, senior developers may also review the problem ticket and offer their own opinion or suggestions in the comments. &lt;/p&gt;

&lt;h2&gt;
  
  
  Code Review
&lt;/h2&gt;

&lt;p&gt;In my experience with various activities, including fiction writing, drawing, and coding, one thing remains consistent - after working on something for a period of time, it becomes easy to lose a "fresh glance" on the project. This is simply a biological response in the brain to conserve resources. While taking a break from the work for several days can help regain a fresh perspective, a quicker and more effective solution is to ask someone else to review your work.&lt;/p&gt;

&lt;p&gt;This is where code review comes into play. While some may see code review as a way for senior developers to mentor junior developers, I see it as an &lt;strong&gt;opportunity for knowledge sharing&lt;/strong&gt;. Developers can ask questions about the code or project, which can lead to valuable insights and learning opportunities. Even a junior developer who may not feel confident in contributing to the code itself can still test the PR code and provide valuable feedback by identifying and reporting a bug. Comments with attached screenshots can be especially helpful in this case.&lt;/p&gt;

&lt;p&gt;In this way, code review becomes a collaborative effort that allows all team members to learn from each other and improve their skills. &lt;/p&gt;

&lt;p&gt;When code review for a pull request (PR) starts to take up too much time, it's not uncommon for the developer who is most responsible for meeting sprint goals to step in and have the final say in any ongoing PR discussions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meetings
&lt;/h2&gt;

&lt;p&gt;Organizing weekly 15-minute one-on-one meetings with each junior developer can be an effective way to monitor their progress and ensure that they are growing and developing in their role.&lt;/p&gt;

&lt;p&gt;During these meetings, it's a good idea to ask the developer about any new knowledge or skills they have acquired over the past week. This can help you understand their strengths and weaknesses, as well as identify areas where they may need additional support or guidance.&lt;/p&gt;

&lt;p&gt;Additionally, it's important to ask how the developer felt about the tickets they worked on during the week. This can help identify any areas where they may be struggling, as well as celebrate their successes and acknowledge their hard work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Mentoring junior developers can be compared to raising children - it requires patience, guidance, and encouragement. &lt;/p&gt;

&lt;p&gt;As a mentor, it's important to give your mentees space and time to learn and grow on their own. This may mean stepping back and allowing them to tackle a problem independently, even if it means they make mistakes along the way. &lt;/p&gt;

&lt;p&gt;Just like with children, it's important to encourage junior developers not to compare themselves to others. Instead, they should focus on their own progress and growth over time. By tracking their own progress and setting achievable goals, they can stay motivated and build the skills they need to succeed.&lt;/p&gt;

&lt;p&gt;The difference is that meeting sprint deadlines is crucial. If you're unsure about a developer's level of expertise, it's best to assign tasks with lower priority. That way, if the deadline is missed, it won't have a significant impact. However, if a ticket with an upcoming deadline needs to be completed, consider pairing up the junior developer with another experienced developer. &lt;/p&gt;

&lt;p&gt;The junior devs should learn how to keep other devs in the loop efficiently but you also have to approximately track their time by yourself (based on information you receive at daily standups) and act if the ticket takes too long.&lt;/p&gt;

</description>
      <category>mentoring</category>
    </item>
    <item>
      <title>Effective Frontend Test Strategy and some notes about Cypress</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Mon, 27 Feb 2023 17:38:46 +0000</pubDate>
      <link>https://dev.to/whatever/effective-frontend-test-strategy-and-some-notes-about-cypress-32p8</link>
      <guid>https://dev.to/whatever/effective-frontend-test-strategy-and-some-notes-about-cypress-32p8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2Fvqr4fbtnxceixwzy50f9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fvqr4fbtnxceixwzy50f9.jpg" alt=" " width="299" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a developer, I frequently find myself working on projects that lack a dedicated testing team or resources. As someone who has spent a noticeable amount of time performing manual testing, fixing frontend unit tests, and writing end-to-end Cypress tests to ensure the highest code quality possible under high business pressure, I have developed some strong opinions about organizing testing strategies in such circumstances. &lt;/p&gt;

&lt;h2&gt;
  
  
  Time for testing
&lt;/h2&gt;

&lt;p&gt;From my experience, usually there is no time specifically reserved for tech debt or automated testing. Generally, every day the business is like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F96kzd92prhbgkjjn015e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F96kzd92prhbgkjjn015e.jpg" alt=" " width="420" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is some time, though, during which developers have to do regression before they show the code to the client/product manager. However, this process can be time-consuming and overwhelming, taking up several hours or even an entire day!&lt;/p&gt;

&lt;p&gt;I'll be talking about the case when you are often asked to do manual regression and you don't have much time to make your life easier, only little time slots here and there &lt;em&gt;(e.g. when the board is not so busy, you've made some PR's and have something to do while you wait for other devs to review them)&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test pyramid
&lt;/h2&gt;

&lt;p&gt;Let's talk about tests for React or Angular. To spend less time developing them you will want to have more &lt;strong&gt;presentation (dumb)&lt;/strong&gt; components and less &lt;strong&gt;smart&lt;/strong&gt; components. &lt;/p&gt;

&lt;p&gt;If you have a lot of complicated web forms it makes sense to use &lt;a href="https://storybook.js.org" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; and write a storybook test for each such form realised as a &lt;strong&gt;dumb&lt;/strong&gt; component. &lt;/p&gt;

&lt;p&gt;When you have written a bunch of tests for &lt;strong&gt;smart&lt;/strong&gt; React/Angular components, you might find out that it's hard to maintain them, because each test has a lot of dependencies and json mocks that you have to update quite often. Given that bringing a test back to life might take 2-3 hours &lt;em&gt;(and I haven't even included in this estimation time for other devs to code review it)&lt;/em&gt; my recommendation is to save efforts and skip tests for most of the features. Think of the &lt;strong&gt;most critical parts&lt;/strong&gt; that your app has instead. E.g. if you do payment operations through your app it makes sense to write as much tests as you can to make sure that money goes where it's supposed to! In other words, before you create a test for a &lt;strong&gt;smart&lt;/strong&gt; component/service/module think: &lt;em&gt;"is it worth supporting such test? How often it's used by other modules? How critical is the feature?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Some developers might argue that you can make make your code more testable: e.g. extract some pure functions into separate modules that can be easily tested by using simple Jest unit tests. The thing is, when you join a large legacy project, in most cases the team won't be willing to do any radical change to existing code unless you really sell the idea that you can make everybody's life better by refactoring this piece of code and you can do it quickly enough.&lt;/p&gt;

&lt;p&gt;I've found that writing &lt;strong&gt;end-to-end (e2e) "happy scenario"&lt;/strong&gt; tests for the most critical scenarios is the most effective solution. E.g. you can write tests for cases when user successfully &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;logs in,&lt;/li&gt;
&lt;li&gt;signs up,&lt;/li&gt;
&lt;li&gt;restores password. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My preferred tool for e2e testing is &lt;strong&gt;Cypress&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPD.&lt;/strong&gt; Recently I've tried &lt;em&gt;"@testing-library/react"&lt;/em&gt;+&lt;em&gt;"@testing-library/user-event"&lt;/em&gt; and it turned out not so bad! Don't have resources to write about it now, but hopefully will make another post about React unit tests in the nearest future. TLDR is I would replace some bits of Cypress with unit tests with these libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cypress
&lt;/h2&gt;

&lt;p&gt;Cypress has well maintained documentation, they even have a section about &lt;a href="https://docs.cypress.io/guides/references/best-practices" rel="noopener noreferrer"&gt;best practices&lt;/a&gt; which I highly recommend to read. I would just like to mention several things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Selecting elements for test&lt;/strong&gt;&lt;br&gt;
You can use &lt;em&gt;data-qa&lt;/em&gt; attributes in your HTML and select elements in test 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;cy.get('[qa="company-name"]').type('test-company');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Long tests issues&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cypress doesn't like tests that take too much time to run. If a test takes too much time, Cypress can throw one of the following errors (there are GitHub issues about that - &lt;a href="https://github.com/cypress-io/cypress/issues/6458" rel="noopener noreferrer"&gt;first&lt;/a&gt;, &lt;a href="https://github.com/cypress-io/cypress/issues/5480" rel="noopener noreferrer"&gt;second&lt;/a&gt;). I've mentioned some ways to deal with it in this &lt;a href="https://dev.to/whatever/the-why-and-how-to-reset-the-database-after-each-test-run-cypress-mongo-5011-react-example-8km"&gt;post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wait&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is only one situation I can imagine where you might want to write something like&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;You are probably in a hurry and you plan to run Cypress tests only locally. Such tests will be very flaky if you run them as a part of CI/CD pipeline!&lt;/p&gt;

&lt;p&gt;Waiting for a HTTP request to finish is covered well enough in the docs. Let's look at a couple of other useful approaches that I've also been using.&lt;/p&gt;

&lt;p&gt;First of all, you can ask Cypress to wait until some thing is visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.get('[data-qa="sign-out-btn"]').should("be.visible");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second of all, you can use constructions like this (in tests or cypress commands):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.request({ ... }).then((response) =&amp;gt; {...});
cy.then(()=&amp;gt; { cy.request({ ... }).then((response) =&amp;gt; {...});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Localstorage and setting env variables&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cy.request({...}).then((response) =&amp;gt; {
  window.localStorage.setItem('token', response.body.token);
  Cypress.env('userId', response.body.data.id);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to reset database after tests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have mongo, I have written a &lt;a href="https://dev.to/whatever/the-why-and-how-to-reset-the-database-after-each-test-run-cypress-mongo-5011-react-example-8km"&gt;post about it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have &lt;a href="https://blog.knoldus.com/how-to-do-database-integration-with-cypress/" rel="noopener noreferrer"&gt;mysql&lt;/a&gt; - this might help. I haven't tried it, so not a legal advice! :)&lt;/p&gt;

</description>
      <category>testing</category>
      <category>cypress</category>
      <category>automation</category>
      <category>strategy</category>
    </item>
    <item>
      <title>The why and how to reset the database after each test run (Cypress, Mongo 5.0.11, React example)</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Mon, 27 Feb 2023 07:03:16 +0000</pubDate>
      <link>https://dev.to/whatever/the-why-and-how-to-reset-the-database-after-each-test-run-cypress-mongo-5011-react-example-8km</link>
      <guid>https://dev.to/whatever/the-why-and-how-to-reset-the-database-after-each-test-run-cypress-mongo-5011-react-example-8km</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2F04oq3c8op2yian7wd3hn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F04oq3c8op2yian7wd3hn.jpg" alt="Image description" width="600" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a developer, I frequently find myself working on projects that lack a dedicated testing team or resources. To minimize the amount of manual regression testing I have to do before deployment to staging, I've found that writing end-to-end (e2e) tests for the most critical scenarios is the most effective solution. My preferred tool for e2e testing is Cypress.&lt;/p&gt;

&lt;p&gt;However, a question that often arises is: how can we ensure that each of these tests can be &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;run multiple times;&lt;/li&gt;
&lt;li&gt;run independently. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's why we need a way to reset the database after each test.&lt;/p&gt;

&lt;p&gt;My approach is based on &lt;a href="https://glebbahmutov.com/blog/testing-mongo-with-cypress/" rel="noopener noreferrer"&gt;Gleb Bahmutov's post&lt;/a&gt;. The difference is that this post is for mongo 5.0.11, and his post is for older mongo versions. &lt;/p&gt;

&lt;p&gt;Another difference from Gleb's post is that all the tests I'll talk about will be about app entry flows: &lt;strong&gt;Sign up&lt;/strong&gt;, &lt;strong&gt;Log in&lt;/strong&gt; and &lt;strong&gt;Logged in&lt;/strong&gt; tests.&lt;/p&gt;

&lt;p&gt;Let's consider a following example (repository is &lt;a href="https://github.com/indra-uolles/restaurants-nodejs-mongo" rel="noopener noreferrer"&gt;here&lt;/a&gt;) &lt;/p&gt;

&lt;p&gt;Btw Cypress &lt;a href="https://docs.cypress.io/guides/references/best-practices#Using-after-or-afterEach-hooks" rel="noopener noreferrer"&gt;recommends&lt;/a&gt; to clean up database &lt;strong&gt;before&lt;/strong&gt; each test. I wrote "after" in the post header only for SEO purposes. &lt;/p&gt;

&lt;h3&gt;
  
  
  Sign up Test
&lt;/h3&gt;

&lt;p&gt;You have written a test for sign up scenario. First time test passed. You try to run the test again and get an error "Email address already exists":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fuyk5hxjn0efdq08ch8lq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fuyk5hxjn0efdq08ch8lq.jpg" alt="Image description" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might want to skip what I've written below and just take a look to branch &lt;strong&gt;feature-cypress-reset&lt;/strong&gt; in the repository instead. There you will see a signup test that can be run an indefinite amount of times.&lt;/p&gt;

&lt;p&gt;File cypress/support/db.js helps to connect to the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F823aih8dpd9jy4m8ay51.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F823aih8dpd9jy4m8ay51.jpg" alt="Image description" width="800" height="765"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are a frontend, you don't have to worry much about refactoring this file. Devops that will convert your PR into working version will change &lt;strong&gt;uri&lt;/strong&gt; and &lt;strong&gt;client.db("rests")&lt;/strong&gt; to something that works for your company. They will set up a separate testing environment that includes a test database.  This test environment will allow run tests without the fear of damaging or corrupting important data in the production system.&lt;/p&gt;

&lt;p&gt;The most interesting file to look at is &lt;strong&gt;cypress.config.ts&lt;/strong&gt;. I spent some time trying to understand why await &lt;strong&gt;users.remove({})&lt;/strong&gt; doesn't work before I realised that it was deprecated in newer mongo and replaced with &lt;strong&gt;deleteMany&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F64czo1vk0m904op0d0lu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F64czo1vk0m904op0d0lu.jpg" alt="Image description" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then you just add a cypress command for cleanup:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Focsoaduswrdnnrbjmc6w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Focsoaduswrdnnrbjmc6w.jpg" alt="Image description" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And use it in the test like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fdr1li9nxh4l01t65zi0n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fdr1li9nxh4l01t65zi0n.jpg" alt="Image description" width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Login Test
&lt;/h3&gt;

&lt;p&gt;When I've started to write tests for logged in users, I've discovered that Cypress doesn't like tests that take too much time to run. If test takes too much time, Cypress can throw one of the following errors (there are GitHub issues about that - &lt;a href="https://github.com/cypress-io/cypress/issues/6458" rel="noopener noreferrer"&gt;first&lt;/a&gt;, &lt;a href="https://github.com/cypress-io/cypress/issues/5480" rel="noopener noreferrer"&gt;second&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;abort test running with some message about web sockets;&lt;/li&gt;
&lt;li&gt;abort typing into form fields, e.g. instead of typing "&lt;a href="mailto:somebody@gmail.com"&gt;somebody@gmail.com&lt;/a&gt;" type "somebody@gma".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best thing is you can do for such tests is to use shortcuts. E.g. instead if imitating user login by typing values into forms, send a POST request using Cypress command. Or change a database record directly using Cypress task.&lt;br&gt;
Also, this setting might help:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fgqlxb1tabgihwljck1xa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fgqlxb1tabgihwljck1xa.jpg" alt="Image description" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cypress suggests to do &lt;a href="https://docs.cypress.io/api/commands/session#Switching-sessions-inside-tests" rel="noopener noreferrer"&gt;session switching inside tests&lt;/a&gt; but we don't use it. Sadly I don't remember any details about why it wasn't useful for our current project.&lt;/p&gt;

&lt;p&gt;Let's say you want to test login flow. You'll need to have a user in your DB before the test!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F8rld40fnh9pmxxcmy9xi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8rld40fnh9pmxxcmy9xi.jpg" alt="Image description" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fn2pzjk22g8esn2sxlv2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fn2pzjk22g8esn2sxlv2y.png" alt="Image description" width="800" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F0lbzj3eqlx6w0t57s14k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0lbzj3eqlx6w0t57s14k.jpg" alt="Image description" width="800" height="757"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might wonder how I got an encrypted version for password that I decided to use. I temporarily put in app.js the following code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fbacdhkb9e51piyz47zpk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fbacdhkb9e51piyz47zpk.jpg" alt="Image description" width="800" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Logged in Test
&lt;/h3&gt;

&lt;p&gt;Let's say we want to test something for a logged in user. We will use a shortcut for logging in, as it is advised in Cypress docs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fb9543eugbyhqrrh6ophc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fb9543eugbyhqrrh6ophc.jpg" alt="Image description" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we'll use it like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F6xvzrpegzfp58zyui8td.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F6xvzrpegzfp58zyui8td.jpg" alt="Image description" width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I would like to tell more about Cypress but this post is too long already :( The only thing that I would like to mention (again) is that if you are a dev who worries about QA but doesn't have much time for it Cypress is definitely the best choice based on the ratio how much time you spend writing/maintaining tests vs how much functionality you get tested. &lt;/p&gt;

</description>
      <category>cypress</category>
      <category>mongodb</category>
      <category>react</category>
      <category>testing</category>
    </item>
    <item>
      <title>Uploading Source Maps for Angular</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Wed, 08 Feb 2023 22:00:34 +0000</pubDate>
      <link>https://dev.to/whatever/uploading-source-maps-for-angular-1jg2</link>
      <guid>https://dev.to/whatever/uploading-source-maps-for-angular-1jg2</guid>
      <description>&lt;p&gt;Tired of sifting through confusing Sentry error messages? You're not alone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fgshf0l0a3k3wmz26quv9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fgshf0l0a3k3wmz26quv9.jpg" alt="Image description" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently struggled with uploading sourcemaps to Sentry, but after some head-banging and persistence, I've gained valuable experience that I want to share with you. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPD. This post has been updated after a timely &lt;a href="https://github.com/getsentry/sentry-javascript/issues/7234" rel="noopener noreferrer"&gt;follow up call&lt;/a&gt; with Sentry team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The task was to organise uploading sourcemaps process for our Angular application. However, these steps could also be useful for those working with React applications. &lt;/p&gt;

&lt;p&gt;To get started, I organized a testing environment by creating a simple app using the &lt;code&gt;ng new&lt;/code&gt; command. I then connected my personal Sentry account and added the &lt;code&gt;Sentry.captureException("...")&lt;/code&gt; function to the click event of a button. To easily deploy the app, I utilized the user-friendly service Netlify (which I highly recommend).&lt;/p&gt;

&lt;p&gt;While I don't want to go into too much detail about setting the release version, I understand that some readers may be interested in exploring different approaches. If that's the case, I encourage you to take a look at this &lt;a href="https://github.com/angular/angular-cli/issues/5190" rel="noopener noreferrer"&gt;discussion&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Settings in angular.json should be 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;"sourceMap": {
  "scripts": true,
  "hidden": true,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To simplify the process, I have compiled all the necessary commands into a bash script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version_str=$(grep -Eo '\"version\"\:\s\"[0-9]\.[0-9]\.[0-9]+\"' package.json)
version=$(echo $version_str | grep -Eo '[0-9]\.[0-9]\.[0-9]+')
version="$version-production"
sentry-cli releases new "$version"
sentry-cli releases set-commits --auto "$version"
sentry-cli releases files "$version" upload-sourcemaps docs/
sentry-cli releases new "$version" --finalize
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also I have put all necessary auth credentials to .sentryclirc file 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;[defaults]
org = &amp;lt;my-organisation-name&amp;gt;
project = &amp;lt;my-project-name&amp;gt;

[auth]
token=&amp;lt;my-token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing all this you might still see *.map files in your build folder, but don't worry, they won't be visible in production. &lt;/p&gt;

</description>
      <category>sentry</category>
      <category>angular</category>
    </item>
    <item>
      <title>My machine-learning pet project. Part 5. Exploring epochs and batches</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Wed, 10 Aug 2022 21:43:18 +0000</pubDate>
      <link>https://dev.to/whatever/my-machine-learning-pet-project-part-5-exploring-epochs-and-batches-3jnj</link>
      <guid>https://dev.to/whatever/my-machine-learning-pet-project-part-5-exploring-epochs-and-batches-3jnj</guid>
      <description>&lt;p&gt;My pet-project is about food recognition. More info &lt;a href="https://dev.to/whatever/my-machine-learning-pet-project-part-1-9o2"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fznblnj5h328btsjzqisu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fznblnj5h328btsjzqisu.jpg" alt="Image description" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last thing I did was to feed a part of my dataset to &lt;a href="https://github.com/fizyr/keras-retinanet" rel="noopener noreferrer"&gt;Retinanet&lt;/a&gt;. This part consisted of 71 images. Retinanet basically complained that my dataset was too small for training. &lt;/p&gt;

&lt;p&gt;It said, &lt;em&gt;"Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least steps_per_epoch * epochs batches"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I looked up epochs and batch sizes. One training &lt;em&gt;epoch&lt;/em&gt; means that the learning algorithm has made one pass through the training dataset, where examples were separated into randomly selected &lt;em&gt;“batch size”&lt;/em&gt; groups. But I've just remembered that 1 picture is worth a 1000 words, so I've drawn a picture for you, check this out:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fchuje3i5d0qr04aivkev.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fchuje3i5d0qr04aivkev.jpeg" alt="Image description" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;steps_per_epoch (or steps) is number of batches to run per training epoch. So if we have batch_size = 32, with 71 images we can break dataset into 2 batches (=2 steps). 64 images will be used for training, and 7 images will be redundant. &lt;/p&gt;

&lt;p&gt;I excluded 7 images from my little dataset and ran command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keras_retinanet/bin/train.py csv dataset/annotations3.csv dataset/labels.csv --epochs 50 --steps 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but I got a message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed to load the native TensorFlow runtime.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It means I forgot to load the environment where Tensorflow had been installed. I ran command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;conda activate mlp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;repeated the train.py command, and ran into a different error message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;train.py: error: unrecognized arguments: --epochs 50 --steps 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After reading this &lt;a href="https://github.com/fizyr/keras-retinanet/issues/929" rel="noopener noreferrer"&gt;issue&lt;/a&gt; I realised that I needed to change my command to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keras_retinanet/bin/train.py --epochs=50 --steps=2 csv dataset/annotations3.csv dataset/labels.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that Retinanet started working and finished its calculations without errors:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F0fss5ib9g9o3gc4u7lsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0fss5ib9g9o3gc4u7lsc.png" alt="Image description" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next time I'll try to plan my real dataset size, I need to find a compromise between what I can label and what amount needs to be labelled. I'll research the methods for making the most of small sized datasets. &lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>imagerecognition</category>
    </item>
    <item>
      <title>My machine-learning pet project. Part 4. Feeding the dataset to Retinanet</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Sun, 26 Jun 2022 10:02:51 +0000</pubDate>
      <link>https://dev.to/whatever/my-machine-learning-pet-project-part-4-feeding-the-dataset-to-retinanet-2gg8</link>
      <guid>https://dev.to/whatever/my-machine-learning-pet-project-part-4-feeding-the-dataset-to-retinanet-2gg8</guid>
      <description>&lt;p&gt;My pet-project is about food recognition. More info &lt;a href="https://dev.to/whatever/my-machine-learning-pet-project-part-1-9o2"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fd19bd3znxg1v1yroz8kf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fd19bd3znxg1v1yroz8kf.jpg" alt="Image description" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Meme from &lt;a href="https://www.reddit.com/r/machinelearningmemes/comments/gtcndr/pip_install_keras/" rel="noopener noreferrer"&gt;csteinmetz1&lt;/a&gt; on reddit
&lt;/h6&gt;

&lt;p&gt;Today I want to feed my dataset to &lt;a href="https://github.com/fizyr/keras-retinanet" rel="noopener noreferrer"&gt;Retinanet&lt;/a&gt; using a csv format. For now, I am going to use only 2 labels and about 80 images (half labelled Salad, half labelled Pastry) just to try Retinanet, to get an idea how it works. &lt;/p&gt;

&lt;p&gt;According to retinanet readme, annotations file should 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;pic-037.jpg,80,20,500,120,Salad
pic-025.jpg,520,250,1152,953,Pastry
pic-with-nothing.jpg,,,,,
pic-004.jpg,0,0,1600,1113,Salad
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But &lt;a href="https://scrapy.org/" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; made me a csv file 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;Apple Cake,"Some apple cake description...",https://www.some-recipes-website.ru/binfiles/images/20200109/m12b509e.jpg,"[{'url': 'https://www.some-recipes-website.ru/binfiles/images/20200109/m12b509e.jpg', 'path': 'full/ae00a78059ad08506aa4767ed925bef5dccabf63.jpg', 'checksum': '55088c744a564af5ed8d4e5ea6478d20', 'status': 'downloaded'}]"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the first thing I did was to write a small &lt;a href="https://gist.github.com/indra-uolles/ec64b64d531acbe517fbb4df718ef894" rel="noopener noreferrer"&gt;Python script&lt;/a&gt; which converted Scrapy csv to a Retinanet csv.&lt;/p&gt;

&lt;p&gt;I spent some time wondering what are the requirements for the images in the dataset. I found one opinion &lt;a href="https://github.com/fizyr/keras-retinanet/issues/992" rel="noopener noreferrer"&gt;here&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No need to rescale your image, because RetinaNet resize the image to get the appropriate size by default.&lt;br&gt;
In general I would advise to keep your settings the same during inference and training.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok, so I won't do anything about images resolution - for now. &lt;/p&gt;

&lt;p&gt;Then I needed to install Retinanet on my computer. I cloned the &lt;a href="https://github.com/fizyr/keras-retinanet" rel="noopener noreferrer"&gt;repo&lt;/a&gt; and went to its root. &lt;/p&gt;

&lt;p&gt;I have macOS Monterey, arm 64. The biggest challenge was to install tensorflow, which was one of Retinanet dependencies.&lt;/p&gt;

&lt;p&gt;I followed this &lt;a href="https://caffeinedev.medium.com/how-to-install-tensorflow-on-m1-mac-8e9b91d93706" rel="noopener noreferrer"&gt;article&lt;/a&gt;. Installed conda, then&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;conda create --name mlp python=3.8
conda activate mlp
conda install -c apple tensorflow-deps
pip install tensorflow-macos
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I copied the dataset files (csv and images) to the root of retinanet repo. Made labels.csv:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Salad,0
Pastry,1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I followed retinanet Readme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install . --user
python setup.py build_ext --inplace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tried to run training script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keras_retinanet/bin/train.py csv dataset/annotations.csv dataset/labels.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but Retinanet said:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ValueError: invalid CSV annotations file: dataset/annotations.csv: line 1: malformed x1: invalid literal for int() with base 10: '43.0'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I fixed the annotations file so it contained integer coordinates instead of float ones and repeated the attempt.&lt;/p&gt;

&lt;p&gt;Retinanet worked for about 3 mins and said:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least steps_per_epoch * epochs batches (in this case, 2 batches). You may need to use the repeat() function when building your dataset.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, that wasn't unexpected (because I had only about 80 images in my dataset, remember?). I don't know what epochs are at the moment, but I will find it out while writing a next post.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>imagerecognition</category>
    </item>
    <item>
      <title>My machine-learning pet project. Part 3. Brushing up and labelling my dataset.</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Sun, 12 Jun 2022 18:25:27 +0000</pubDate>
      <link>https://dev.to/whatever/my-machine-learning-pet-project-part-3-brushing-up-and-labelling-my-dataset-1mlo</link>
      <guid>https://dev.to/whatever/my-machine-learning-pet-project-part-3-brushing-up-and-labelling-my-dataset-1mlo</guid>
      <description>&lt;p&gt;My pet-project is about food recognition. More info &lt;a href="https://dev.to/whatever/my-machine-learning-pet-project-part-1-9o2"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fj1596ytpl16yteug1wf9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fj1596ytpl16yteug1wf9.jpeg" alt="Image description" width="250" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://scrapy.org/" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; made me a folder with images and a .csv with rows like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apple Cake,"Some apple cake description...",https://www.some-recipes-website.ru/binfiles/images/20200109/m12b509e.jpg,"[{'url': 'https://www.some-recipes-website.ru/binfiles/images/20200109/m12b509e.jpg', 'path': 'full/ae00a78059ad08506aa4767ed925bef5dccabf63.jpg', 'checksum': '55088c744a564af5ed8d4e5ea6478d20', 'status': 'downloaded'}]"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I needed to create .csv files 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;pic-037.jpg,80,20,500,120,risotto
pic-025.jpg,520,250,1152,953,risotto
pic-with-nothing.jpg,,,,,
pic-004.jpg,0,0,1600,1113,beans
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To do that, I googled smth like "best machine learning label tools 2022" and found &lt;a href="https://labelstud.io/" rel="noopener noreferrer"&gt;Label-studio&lt;/a&gt;. I followed these steps from their docs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 -m venv env
source env/bin/activate
python -m pip install label-studio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I couldn't launch label-studio until I did some of these things:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install wheel
pip install spacy
pip install cymem
brew install postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(&lt;a href="https://github.com/explosion/cymem/issues/10" rel="noopener noreferrer"&gt;link1&lt;/a&gt;, &lt;a href="https://bobcares.com/blog/error-pg_config-executable-not-found/" rel="noopener noreferrer"&gt;link2&lt;/a&gt; might be helpful)&lt;/p&gt;

&lt;p&gt;I didn't have any problems importing my data to Label-studio. The only setting I had to do was to add my labeling interface code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View&amp;gt;
  &amp;lt;Image name="image" value="$image"/&amp;gt;
  &amp;lt;Choices name="choice" toName="image" showInLine="true"&amp;gt;
    &amp;lt;Choice value="Salad" background="blue"/&amp;gt;
    &amp;lt;Choice value="Soup" background="green" /&amp;gt;
    &amp;lt;Choice value="Pastry" background="orange" /&amp;gt;
    &amp;lt;Choice value="Nothing" background="orange" /&amp;gt;
  &amp;lt;/Choices&amp;gt;
  &amp;lt;RectangleLabels name="label" toName="image"&amp;gt;
    &amp;lt;Label value="Salad" background="green"/&amp;gt;
    &amp;lt;Label value="Soup" background="blue"/&amp;gt;
    &amp;lt;Label value="Pastry" background="orange"/&amp;gt;
    &amp;lt;Label value="Nothing" background="black"/&amp;gt;
  &amp;lt;/RectangleLabels&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, labeling interface looked like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F3iceftmequ9miufeheg6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3iceftmequ9miufeheg6.jpg" alt="Image description" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had label "Nothing" for confusing images that I decided to exclude from the dataset:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fkr96paasxxyhe8z77i90.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkr96paasxxyhe8z77i90.jpg" alt="Image description" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After I finished labeling a portion of images, I chose to export them in .csv format. I got a file with rows 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;/data/upload/1/83d8ce57-7478f053119ca2a85c4932870ef3e1833eb3eeb5.jpg,14,Pastry,"[{""x"": 13.157894736842104, ""y"": 6.5625, ""width"": 41.578947368421055, ""height"": 74.375, ""rotation"": 0, ""rectanglelabels"": [""Pastry""], ""original_width"": 570, ""original_height"": 320}]",1,20,2022-06-06T07:11:56.377261Z,2022-06-10T21:02:35.758255Z,1209.599
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I was surprised when I saw x, y, width and height. Then I've read in the docs that &lt;em&gt;"Image annotations exported in JSON format use percentages of overall image size, not pixels, to describe the size and location of the bounding boxes."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I wrote a small python script to check exported regions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from PIL import Image
img = Image.open('../../images/full/7478f053119ca2a85c4932870ef3e1833eb3eeb5.jpg')

x = 13.157894736842104
y = 6.5625
width = 41.578947368421055
height = 74.375
original_width = 570
original_height = 320

pixel_x = x / 100.0 * original_width
pixel_y = y / 100.0 * original_height
pixel_width = width / 100.0 * original_width
pixel_height = height / 100.0 * original_height

left = pixel_x
upper = pixel_y
right = pixel_x + pixel_width
lower = pixel_y + pixel_height

box = (left, upper, right, lower)
region = img.crop(box)
region.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I launched the script, it showed me the correct region cropped out of the original image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fql16qnuh0fj64325hsm1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fql16qnuh0fj64325hsm1.jpg" alt="Image description" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So now I understood how to get pixel annotations if I need them. &lt;/p&gt;

&lt;p&gt;Next post is going to be about trying to feed the dataset to Retinanet. I am going to use only 48 images scraped so far just to see what format of input it really needs.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>imagerecognition</category>
    </item>
    <item>
      <title>My machine-learning pet project. Part 2. Preparing my dataset</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Thu, 02 Jun 2022 22:17:36 +0000</pubDate>
      <link>https://dev.to/whatever/my-machine-learning-pet-project-part-2-preparing-my-dataset-4kee</link>
      <guid>https://dev.to/whatever/my-machine-learning-pet-project-part-2-preparing-my-dataset-4kee</guid>
      <description>&lt;p&gt;My pet-project is about food recognition. More info &lt;a href="https://dev.to/whatever/my-machine-learning-pet-project-part-1-9o2"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmwz2ctxia0ikdyd3lstk.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmwz2ctxia0ikdyd3lstk.jpeg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Data sets in tutorials vs data sets in the wild. From &lt;a href="https://twitter.com/towards_AI/status/1332567246011555840?s=20" rel="noopener noreferrer"&gt;Towards AI&lt;/a&gt; on Twitter
&lt;/h6&gt;

&lt;p&gt;First thing that came to my mind was to scrape stuff from some instagram account. Have you seen how many recipes are there??? Millions. And they have descriptions, from which I could extract labels. I thought it would be ez. I managed to scrape about 10 posts using this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;instaloader&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="nx"&gt;nytcooking&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;videos&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;slide&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date_utc &amp;gt;= datetime(2012, 5, 21)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;sanitize&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far so good. But then I tried to scrape a bit more, e.g. posts for 3 months, and started getting 429 Too many requests errors. Creating new instagram profiles didn't help. How could I, alone, beat an army of well paid developers? I needed another approach. &lt;/p&gt;

&lt;p&gt;I chose one of the recipe websites that I used to visit. It has good photos and descriptions and it's easy to scrape. I picked &lt;a href="https://scrapy.org/" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; to do the job. It's actively supported (last commit - 5 days ago), has good documentation and a readable code.&lt;/p&gt;

&lt;p&gt;I saved one sample webpage to my desktop and launched &lt;a href="https://docs.scrapy.org/en/latest/topics/shell.html" rel="noopener noreferrer"&gt;scrapy shell&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scrapy shell ../Desktop/test.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It helped me to prepare a bunch of selectors 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;recipe.xpath('./p[@class="material-anons__des"]//text()').get()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I created a project template using command 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;scrapy startproject myproject [project_dir]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I took a look at their &lt;a href="https://github.com/scrapy/quotesbot/tree/master/quotesbot/spiders" rel="noopener noreferrer"&gt;example repo at github&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The only thing I have struggled for some time was item pipelines. At one point I copied some stuff from stackoverflow to &lt;em&gt;settings.py&lt;/em&gt;. And scrapy started to complain, smth like &lt;em&gt;file A&lt;/em&gt; has an error now. I went to scrapy github and found a nice little comment in &lt;em&gt;file A&lt;/em&gt; about what really should be in the settings file now. So that's what I added to settings.py:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FILES_STORE = './csv'
IMAGES_STORE = './images'
ITEM_PIPELINES = {
    'scrapy.pipelines.images.ImagesPipeline': 1
}
FEEDS={
    './csv/items-%(batch_id)d': {
        'format': 'csv'
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These settings allowed me to download images and make a *.csv file with parsed titles,descriptions and image paths urls without writing any extra lines of code. In my opinion, Scrapy is a very powerful instrument, so I totally recommend to use it when you want to scrape some data (not from instagram).&lt;/p&gt;

&lt;p&gt;The next post is going to be about brushing up scraped data and labelling it. &lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>imagerecognition</category>
    </item>
    <item>
      <title>My machine learning pet-project. Part 1</title>
      <dc:creator>Natalia D</dc:creator>
      <pubDate>Wed, 01 Jun 2022 20:06:13 +0000</pubDate>
      <link>https://dev.to/whatever/my-machine-learning-pet-project-part-1-9o2</link>
      <guid>https://dev.to/whatever/my-machine-learning-pet-project-part-1-9o2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.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%2Fkmw9kas1t1rxha106p7p.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkmw9kas1t1rxha106p7p.jpeg" alt="Image description" width="600" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Machine learning has sneaked into our lives. Every night I tell Alexa "turn the lights off". Every day my phone successfully performs face recognition before I pay with it. Given the tremendous improvement of this field I decided to find out how hard nowadays it is for an ordinary frontend engineer to apply machine learning for some task.&lt;/p&gt;

&lt;p&gt;A long, long ago my friend and me used to share photos of what we had eaten during the day. We tried to eat less and make healthier food choices. So I decided to try to make something (a website? some bot? to be refined later), which helps the user to tweet about his recent food choices. Show it the food photos and it creates a tweet code with suitable emojis which you can share. Thanks to Wordle for the inspiration :)&lt;/p&gt;

&lt;p&gt;Of course, being a former researcher the first thing I did was to google what other people have done about food recognition. The most interesting article I found so far is &lt;a href="https://medium.com/smileinnovation/capturing-your-dinner-a-deep-learning-story-bf8f8b65f26f" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I decided to kind of repeat the author's way, but give it a bit of my own tweak. E.g. most probably I'll use 3 labels: pastry, salad and soup. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/whatever/my-machine-learning-pet-project-part-2-preparing-my-dataset-4kee"&gt;Next post&lt;/a&gt; is going to be about how I started to gather the dataset for my project. &lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>imagerecognition</category>
    </item>
  </channel>
</rss>
