<?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: guto</title>
    <description>The latest articles on DEV Community by guto (@guto).</description>
    <link>https://dev.to/guto</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%2F793615%2Fdf4c6400-4ae0-4e53-ab2f-3f5914430bf8.jpeg</url>
      <title>DEV Community: guto</title>
      <link>https://dev.to/guto</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/guto"/>
    <language>en</language>
    <item>
      <title>Meet Datomic: the immutable and functional database.</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Mon, 15 Apr 2024 23:19:16 +0000</pubDate>
      <link>https://dev.to/guto/meet-datomic-the-immutable-and-functional-database-10af</link>
      <guid>https://dev.to/guto/meet-datomic-the-immutable-and-functional-database-10af</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;"When you combine two pieces of data you get data. When you combine two machines you get trouble." - Rich Hickey presenting &lt;a href="https://www.infoq.com/presentations/datomic-functional-database/" rel="noopener noreferrer"&gt;The Functional Database&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Concepts focused on functional programming, mainly on immutability, have been increasingly present in our daily lives, therefore, nothing more fair than getting to know a database whose philosophy is the immutability of data, bringing control of facts in a format completely different from what we are used to.&lt;/p&gt;

&lt;p&gt;In this article, we will get to know Datomic, which has this name precisely because it brings data in a format slightly different from the conventional one, seeking to bring data immutability closer to the database level, with a functional approach focused to work well with distributed systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is Datomic?&lt;/li&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;Data structure&lt;/li&gt;
&lt;li&gt;How a transaction works?&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Datomic?
&lt;/h2&gt;

&lt;p&gt;At the beginning of 2012, the Relevance team (later joining Metadata to form Cognitec), together with Rich Hickey, launched Datomic, which they began working on in 2010, with the main motivation being to transfer a substantial part of the power assigned to database servers for application servers, so that the programmer would have more programming power with data within the application logic.&lt;/p&gt;

&lt;p&gt;Datomic Cloud was released in early 2018 using Amazon's components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DynamoDB, EFS, EBS and S3 as storage services;&lt;/li&gt;
&lt;li&gt;CloudFormation for deployment;&lt;/li&gt;
&lt;li&gt;AWS Cloudwatch for logging, monitoring, and metrics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cognitect (the company previously responsible for developing Datomic) was acquired by Nubank in 2020, and Nubank announced in April 2023 that the Datomic binaries are publicly available and free to use (this means that its Pro version is now free to use).&lt;/p&gt;

&lt;p&gt;Written in Clojure, Datomic works a little differently from the databases we are used to using, being used to manage data, but not store it. We'll go through more details about its architecture, but in short, it means that Datomic can use several other data storage services to store transactions, even other databases, which can result in a nice combination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concept
&lt;/h3&gt;

&lt;p&gt;The main operating concept of Datomic is that the data is immutable as a whole. An interesting analogy for you to imagine and understand how it works a little better is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Imagine a database that you are used to working with, such as PostgreSQL or MySQL;&lt;/li&gt;
&lt;li&gt;Imagine now that you have two tables, a product table, but you also have a log table for these products, storing every modification that was made to the original product table;&lt;/li&gt;
&lt;li&gt;When you update an item, this item has its data modified in the product table, but we add its previous value to the log table, highlighting what was done (in our case an update on its value);&lt;/li&gt;
&lt;li&gt;For Datomic, there would only be the product "table" (in our case &lt;a href="https://docs.datomic.com/pro/schema/schema.html" rel="noopener noreferrer"&gt;schema&lt;/a&gt;), with an additional column, indicating whether that item is true or not, so, when we update the product value, a new line would be added with the new value, however, the old line now has the check column value set to false, after all, it is no longer true at the current time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that past data continues to exist, but there is this representation that indicates whether the value of the product is valid or not. These lines are called facts, so when the word "fact" is mentioned, remember this analogy.&lt;/p&gt;

&lt;p&gt;One point to highlight: remember that no matter how much the value of the product has been changed, it remains a fact - no longer valid for the current time, however, it is still a fact that occurred, after all, the product in the past had this value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;To better understand how everything works within Datomic, we first need to better understand how its architecture works.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can I store data?
&lt;/h3&gt;

&lt;p&gt;As previously mentioned, Datomic is not characterized by storing data as a database in the same way as we are used to, being used mainly to "transact and manage data". You can combine Datomic in different ways, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQL databases (such as PostgreSQL and MySQL);&lt;/li&gt;
&lt;li&gt;DynamoDB (if you choose to use Datomic Cloud, the Indexes will be stored in S3, Transaction Log in DynamoDB and Cache in EFS);&lt;/li&gt;
&lt;li&gt;Cassandra and Cassandra2;&lt;/li&gt;
&lt;li&gt;Dev mode, storing data in memory.
How it works is very simple: depending on your choice, a table will be created within your database in order to store all the data, which Datomic will manage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Peers
&lt;/h3&gt;

&lt;p&gt;Every type of interaction that an application will make with Datomic will be through a Peer, responsible for carrying out a small cache control, assembling and executing queries, bringing indexing data in addition to sending commits. Peers can be used in two main ways, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Peer Library: a &lt;a href="https://mvnrepository.com/artifact/com.datomic/peer" rel="noopener noreferrer"&gt;library&lt;/a&gt; to be added to your dependencies that will always be working with your application, after all, it is through it that you will carry out any type of action with your database;&lt;/li&gt;
&lt;li&gt;Peer Server: being used mainly with the Datomic in Cloud format, your application now has only a &lt;a href="https://mvnrepository.com/artifact/com.datomic/client-cloud" rel="noopener noreferrer"&gt;Client library&lt;/a&gt;, responsible for communicating with the Peer Server that will perform direct actions with Datomic, as well as the Peer Library.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Peers work with a given database value for an extended period of time without concern. These values are immutable and provide a stable, consistent view of data for as long as a needs one, functioning as a kind of "snapshot" of the database to allow data to be returned in a more practical way without overloading with multiple queries in real time . This is a marked difference from relational s which require work to be done quickly using a short-lived. You can see more about the description of how Peers work in &lt;a href="https://docs.datomic.com/pro/overview/architecture.html#storage-services" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An important point to highlight is: if you are using the Peer Library, each node of your application, each service will have a Peer running alongside it, therefore, this means that in the process of a distributed system, these multiple Peers will be responsible for sending commits to your database, however, in a distributed system it is extremely important to control data consistency, after all, if I have multiple services sending queries in parallel, how can I control that the data is truthful and correctly passes a race condition? Well, to understand this better, let's understand what Transactor is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transactor
&lt;/h3&gt;

&lt;p&gt;The &lt;em&gt;Transactor&lt;/em&gt; is responsible for transacting the received commits and storing data within our database. The architecture of an application with Datomic is characterized by having multiple Peers working and sending commits (after all, we will have multiple services), but only a single Transactor, guaranteeing total data consistency. This means that regardless of whether the Transactor is receiving &lt;strong&gt;n&lt;/strong&gt; commits per second, they will all be queued to guarantee total consistency.&lt;/p&gt;

&lt;p&gt;The main point of this architectural format comes from understanding that dealing with concurrency in general, allowing multiple data to be stored in parallel in our database, especially in case of a distributed system, could negatively affect the consistency of stored data, being a drastic problem.&lt;/p&gt;

&lt;p&gt;Now, we can look in more detail at a diagram that demonstrates how this entire architecture behaves:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.datomic.com%2Fpro%2Fimages%2Fclientarch_orig.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.datomic.com%2Fpro%2Fimages%2Fclientarch_orig.svg" alt="Datomic architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note in the diagram above that the Transactor is responsible for all activities that require direct communication with the data storage service used, in addition to controlling data indexing formats, working with a memcached cluster, and responding to commits. Thus, we can state that Datomic deals with &lt;a href="https://www.databricks.com/glossary/acid-transactions" rel="noopener noreferrer"&gt;ACID&lt;/a&gt; transactions, an acronym that refers to the set of 4 key properties that define a transaction: &lt;strong&gt;Atomicity , Consistency, Isolation, and Durability&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage Services
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"Peers read facts from the Storage Services. The facts the Storage Service returns never change, so Peers do extensive caching. Each Peer's cache represents a partial copy of all the facts in the database. The Peer cache implements a least-recently used policy for discarding data, making it possible to work with databases that won't fit entirely in memory. Once a Peer's working set is cached, there is little or no network traffic for reads." - from &lt;a href="https://docs.datomic.com/pro/overview/architecture.html#storage-services" rel="noopener noreferrer"&gt;Datomic Pro Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Storage Services can be configured however you like, all you need to do is create a properties file (called &lt;code&gt;transactor.properties&lt;/code&gt;) to represent how your Transactor will be created and managed.&lt;/p&gt;

&lt;p&gt;So, if you use PostgreSQL, for example, you will have to configure the driver that will be used, the connection url, username and password, and you can also configure values for &lt;code&gt;memory-index-threshold&lt;/code&gt;, &lt;code&gt;memory-index-max&lt;/code&gt; , &lt;code&gt;object-cache-max&lt;/code&gt;, &lt;code&gt;read-concurrency&lt;/code&gt; and even &lt;code&gt;write-concurrency&lt;/code&gt;, ultimately creating a table named &lt;code&gt;datomic_kvs&lt;/code&gt; within your PostgreSQL:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;datomic_kvs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;rev&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;map&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;bytea&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;pk_id&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;OIDS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;FALSE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Data structure
&lt;/h2&gt;

&lt;p&gt;Well, we've already talked about the architecture of how Datomic as a whole works, so now let's better visualize what the basis of Datomic's data structure is like, starting with &lt;em&gt;Datoms&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Datoms
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"A &lt;strong&gt;datom&lt;/strong&gt; is an immutable atomic fact that represents the addition or retraction of a relation between an entity, an attribute, a value, and a transaction."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So basically a datom is a simple fact in log, representing data changes of a relation. We can express a datom as a five-tuple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an entity id (E)&lt;/li&gt;
&lt;li&gt;an attribute (A)&lt;/li&gt;
&lt;li&gt;a value for the attribute (V)&lt;/li&gt;
&lt;li&gt;a transaction id (Tx)&lt;/li&gt;
&lt;li&gt;a boolean (Op) indicating whether the datom is being added or retracted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these are from &lt;a href="https://docs.datomic.com/cloud/whatis/data-model.html#datoms" rel="noopener noreferrer"&gt;Datomic Cloud documentation&lt;/a&gt;. Look at the example below:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;E&lt;/th&gt;
&lt;th&gt;42&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;:user/favorite-color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;V&lt;/td&gt;
&lt;td&gt;:blue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tx&lt;/td&gt;
&lt;td&gt;1234&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Op&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Entities
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"A Datomic entity provides a lazy, associative view of all the information that can be reached from a Datomic entity id."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking into an &lt;a href="https://docs.datomic.com/pro/javadoc/datomic/Entity.html" rel="noopener noreferrer"&gt;Entity&lt;/a&gt; we can visualize as a table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;E&lt;/th&gt;
&lt;th&gt;A&lt;/th&gt;
&lt;th&gt;V&lt;/th&gt;
&lt;th&gt;Tx&lt;/th&gt;
&lt;th&gt;Op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;:user/favorite-color&lt;/td&gt;
&lt;td&gt;:blue&lt;/td&gt;
&lt;td&gt;1234&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;:user/first-name&lt;/td&gt;
&lt;td&gt;"John"&lt;/td&gt;
&lt;td&gt;1234&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;:user/last-name&lt;/td&gt;
&lt;td&gt;"Doe"&lt;/td&gt;
&lt;td&gt;1234&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;:user/favorite-color&lt;/td&gt;
&lt;td&gt;:green&lt;/td&gt;
&lt;td&gt;4567&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;:user/favorite-color&lt;/td&gt;
&lt;td&gt;:blue&lt;/td&gt;
&lt;td&gt;4567&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;Transaction Id&lt;/em&gt; can be visualized as a point of the time which represents that data. In the example above we have &lt;code&gt;1234&lt;/code&gt; and &lt;code&gt;4567&lt;/code&gt;. Look at &lt;code&gt;1234&lt;/code&gt;... In the first row, the &lt;code&gt;:user/favorite-colour&lt;/code&gt; attribute has the value &lt;code&gt;:blue&lt;/code&gt;, with &lt;code&gt;op&lt;/code&gt; as &lt;code&gt;true&lt;/code&gt;. But, in the future, at  &lt;code&gt;4567&lt;/code&gt; now the attribute has the &lt;code&gt;op&lt;/code&gt; set to false for the attribute with the value &lt;code&gt;:blue&lt;/code&gt; (now &lt;code&gt;:green&lt;/code&gt; is set for true).&lt;/p&gt;

&lt;p&gt;For us, we haven't changed manually the &lt;code&gt;Op&lt;/code&gt;. Datomic automatically made this when we updated the value for &lt;code&gt;:user/favorite-color&lt;/code&gt;. That means: Datomic automatically manage our data and set or update values, and we have the exactly point in time which the &lt;code&gt;:user/favorite-color&lt;/code&gt; have been changed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Schemas
&lt;/h3&gt;

&lt;p&gt;As the &lt;a href="https://docs.datomic.com/cloud/schema/defining-schema.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; says: &lt;em&gt;Attributes are defined using the same data model used for application data. That is, attributes are themselves defined by entities with associated attributes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well, for defining a new attribute we need to define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:db/ident&lt;/code&gt;, a name that is unique within the database&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:db/cardinality&lt;/code&gt;, specifying whether entities can have one or a set of values for the attribute&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:db/valueType&lt;/code&gt;, the type allowed for an attribute's value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:db/doc&lt;/code&gt; (optional), the attribute's description/documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Look, all of these &lt;code&gt;:db/ident&lt;/code&gt;, &lt;code&gt;:db/cardinality&lt;/code&gt; and etc are only simple entities which pointer to each other. They are automatically generated by Datomic in the initial stage. This means: they have a default &lt;code&gt;entity id&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How a transaction works?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Every transaction in Datomic is its own entity, making it easy to add facts about why a transaction was added (or who added it, or from where, etc.)"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have "two options" for transactions: &lt;code&gt;add&lt;/code&gt; or &lt;code&gt;retraction&lt;/code&gt;. Every transaction returns the transaction id and the database state before and after the transaction. The forms can be:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:db/add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entity-id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:db/retract&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entity-id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;How we saw before: every transaction occur in a queued mode. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a transaction completes successfully, data is committed to the database and we have a transaction report returned as a map with the following keys:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;key&lt;/th&gt;
&lt;th&gt;usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;:db-before&lt;/td&gt;
&lt;td&gt;database value before the transaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;:db-after&lt;/td&gt;
&lt;td&gt;database value after the transaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;:tx-data&lt;/td&gt;
&lt;td&gt;datoms produced by the transaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;:tempids&lt;/td&gt;
&lt;td&gt;map from temporary ids to assigned ids&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;The database value is like a "snapshot" from the database, as we saw before.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's see an example of how &lt;code&gt;:db/add&lt;/code&gt; works. Look at the example below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;;; We have this schema&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:internal/id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:internal/value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:internal/key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;;; Making a simple transaction&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="no"&gt;:db/add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:internal/value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; This will update the value...&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;;; But, we can perform multiple&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; transactions, look:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="no"&gt;:db/add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:internal/value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:db/add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:internal/key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"another"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; It will work fine.&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;;; But, when we perform something like:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="no"&gt;:db/add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:internal/value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:db/add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:internal/value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;;; We will have a conflict&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;The conflict occur when we have a change in the same entity with the same attribute. That's make sense, because we can't have a fact updating multiple times in the same time lapse.&lt;/p&gt;

&lt;p&gt;A cool fact: if we perform a multiple transaction they occur in parallel (with multiple processing). This is secure because as we saw before, the same attribute can't be updated in the same transaction.&lt;/p&gt;

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

&lt;p&gt;This article and the beginning of this series of articles aims to introduce Datomic and present its various possibilities and advantages for general use. It is important to highlight that the official Datomic documentation is excellent, therefore, for further in-depth research it is extremely important that you use it! And of course, if you want to take your first steps with Datomic, feel free to use Getting Started from the official documentation, but if you want a repository with the codes used, I've made a &lt;a href="https://github.com/lanjoni/datomic-getting-started" rel="noopener noreferrer"&gt;repository available&lt;/a&gt; on my GitHub (don't forget to give a star)!&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>database</category>
      <category>functional</category>
      <category>programming</category>
    </item>
    <item>
      <title>Conhecendo o ecossistema Crystal: ferramentas e projetos</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Mon, 16 Oct 2023 23:26:52 +0000</pubDate>
      <link>https://dev.to/he4rt/conhecendo-o-ecossistema-crystal-ferramentas-e-projetos-49m1</link>
      <guid>https://dev.to/he4rt/conhecendo-o-ecossistema-crystal-ferramentas-e-projetos-49m1</guid>
      <description>&lt;p&gt;Bem, se você abriu esse artigo, então, tenho certeza que está interessado em entender um pouco mais sobre o ecossistema de Crystal. Antes de mais nada, vamos primeiramente introduzir o que é Crystal e onde se aplica.&lt;/p&gt;




&lt;h2&gt;
  
  
  Índice
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;O que é Crystal?&lt;/li&gt;
&lt;li&gt;Ruby e Crystal&lt;/li&gt;
&lt;li&gt;Integração nativa com LibC&lt;/li&gt;
&lt;li&gt;
Ferramentas

&lt;ol&gt;
&lt;li&gt;Language Server Protocol (LSP)&lt;/li&gt;
&lt;li&gt;Read-Eval-Print Loop (REPL)&lt;/li&gt;
&lt;li&gt;Code style linter&lt;/li&gt;
&lt;li&gt;Debugger&lt;/li&gt;
&lt;li&gt;Gerenciador de dependências&lt;/li&gt;
&lt;li&gt;Livro&lt;/li&gt;
&lt;li&gt;Documentação&lt;/li&gt;
&lt;li&gt;Patterns&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;
Frameworks

&lt;ol&gt;
&lt;li&gt;Kemal&lt;/li&gt;
&lt;li&gt;Amber&lt;/li&gt;
&lt;li&gt;Lucky&lt;/li&gt;
&lt;li&gt;Marten&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Projetos com Crystal&lt;/li&gt;
&lt;li&gt;Finalização&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  O que é Crystal?
&lt;/h2&gt;

&lt;p&gt;Crystal é uma linguagem de programação de código aberto, com sintaxe inspirada no Ruby, que visa a produtividade e o desempenho. Ele tem uma sintaxe elegante e uma tipagem estática, mas sem a necessidade de declarar tipos de variáveis. O Crystal é compilado para código nativo, e não para bytecode, e usa LLVM para gerar o código binário.&lt;/p&gt;

&lt;p&gt;A aplicabilidade de Crystal é vasta, podendo ser visto de diferentes formas, mas, consigo afirmar que a ênfase de aplicabilidade ocorre para aplicações web, na qual consegue se destacar em pontos específicos exatamente por ser uma linguagem de programação compilada.&lt;/p&gt;

&lt;p&gt;O principal motivo para o surgimento de Crystal foi para resolver alguns problemas bem específicos que Ruby possuia, porém, seriam solucionados deixando de lado a dinamicidade que Ruby proporcionava para abrir espaço para uma linguagem de programação totalmente nova, com a possibilidade de inferência de tipos, sendo compilada. Assim, em 2011 surge o projeto de uma nova linguagem de programação, criada por &lt;a href="https://github.com/asterite"&gt;Ary Borenszweig&lt;/a&gt;, &lt;a href="https://github.com/waj"&gt;Juan Wajnerman&lt;/a&gt; e &lt;a href="https://github.com/bcardiff"&gt;Brian Cardiff&lt;/a&gt;, contando hoje com mais de 450 colaboradores do mundo todo, tendo seu código fonte disponibilizado no repositório oficial do GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ruby e Crystal
&lt;/h2&gt;

&lt;p&gt;Como citado anteriormente, Ruby por sua vez possui uma sintaxe muito elegante, na qual Crystal se inspirou em sua maior parte exatamente pelo contexto de desenvolvimento da época, desejando uma linguagem de programação elegante na sintaxe como Ruby, veloz como C, podendo ainda realizar otimizações nativas com interoperabilidade utilizando a LibC e o melhor: sem escrever uma linha de código em C. Parece mágica não é? Bem, é apenas Crystal!&lt;/p&gt;

&lt;p&gt;Uma analogia para entender melhor a compatibilidade de ambas as linguagens de programação que gosto de fazer é: imagine que você hoje é dono de uma empresa que possui N desenvolvedores Ruby, que consequentemente são a maioria dentro da empresa. Em um belo dia você em uma conversa com seus arquitetos de software decidem que uma linguagem compilada é necessária em apenas alguns serviços que estão funcionando hoje. Ao invés de simplesmente reescrever todo o código em alguma outra linguagem compilada, você pode reaproveitar toda a base de código para utilizar e compilar em Crystal, assim, a curva de aprendizado para seus desenvolvedores Ruby será praticamente nula, afinal, apenas alguns pontos específicos requerem maior cuidado ao se trabalhar com Crystal, como por exemplo a verificação de tipos, que pode ser um pouco estranho no início, mas, garanto que com o passar do tempo será mais prática a manutenção de seu código.&lt;/p&gt;

&lt;p&gt;Entenda que Crystal não veio &lt;em&gt;para substituir o Ruby&lt;/em&gt;, mas, para que ambos possam ser utilizados em conjunto, visando um melhor aproveitamento de código, melhor eficiência e melhor ambiente de desenvolvimento. O exemplo que deixarei abaixo demonstra a diferença de dois códigos que fazem a mesma coisa, porém, Crystal possui uma peculiaridade específica que vou retratar logo abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;soma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"Digite o primeiro número inteiro: "&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"Digite o segundo número inteiro: "&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"A soma dos números é &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;soma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O código acima é bem simples: pedimos para o usuário informar dois números, &lt;code&gt;a&lt;/code&gt; e &lt;code&gt;b&lt;/code&gt; respectivamente, na qual &lt;code&gt;chomp&lt;/code&gt; remove o enter (&lt;code&gt;\n&lt;/code&gt; ou &lt;code&gt;\r&lt;/code&gt;) e o &lt;code&gt;to_i&lt;/code&gt; converte o valor para inteiro. Agora, em Crystal precisamos apenas adicionar uma validação bem simples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;soma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"Digite o primeiro número inteiro: "&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;gets&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"Digite o segundo número inteiro: "&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;gets&lt;/span&gt;

&lt;span class="c1"&gt;# É necessário validar se o valor é nil!&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Você deve digitar dois números inteiros."&lt;/span&gt;
  &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"A soma dos números é &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;soma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A validação é necessária para não enviarmos um valor nulo para o método &lt;code&gt;chomp&lt;/code&gt;, afinal, ele está esperando receber uma &lt;code&gt;String&lt;/code&gt; e sem a validação estaremos enviando um &lt;code&gt;String | Nil&lt;/code&gt;, não validando com o tipo esperado. Nesse momento você deve estar pensando: &lt;em&gt;mas, os tipos enviados foram validados em tempo de compilação? Isto é, a inferência dos tipos foi feita sem eu precisar falar nada&lt;/em&gt;? Bem, a resposta é &lt;strong&gt;sim&lt;/strong&gt;, o compilador automaticamente &lt;em&gt;adivinhou&lt;/em&gt; de quais tipos se tratavam.&lt;/p&gt;

&lt;p&gt;Certo, agora você deve perguntar: &lt;em&gt;nossa mas eu também consigo inferir os tipos manualmente? Como por exemplo na função &lt;code&gt;soma&lt;/code&gt;, informando os tipos dos parâmetros que espero receber, além do tipo do retorno&lt;/em&gt;? A resposta é &lt;strong&gt;sim&lt;/strong&gt;, e neste caso ficaria algo como o exemplo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;soma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Interessante, certo?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O principal ponto é dar nas mãos do desenvolvedor a possibilidade de &lt;em&gt;nivelar&lt;/em&gt; exatamente o que um método deve ter e/ou deve retornar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integração nativa com LibC
&lt;/h2&gt;

&lt;p&gt;Se você quer utilizar ferramentas da LibC, mas, sem a necessidade de escrever código em C, então Crystal pode te ajudar com isso. Com bindings nativas você pode utilizar bibliotecas externas, incluindo a LibC, para utilizar ferramentas que seriam possíveis apenas escrevendo código nativo em C.&lt;/p&gt;

&lt;p&gt;Para entender um pouco melhor sobre o funcionamento, recomendo seguir a &lt;a href="https://crystal-lang.org/reference/1.10/syntax_and_semantics/c_bindings/lib.html"&gt;documentação oficial&lt;/a&gt;, porém, deixarei um exemplo abaixo,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;lib&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;
  &lt;span class="c1"&gt;# Em C: double cos(double x)&lt;/span&gt;
  &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Float64&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;O exemplo acima demonstra o uso da função &lt;code&gt;cos&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Ferramentas
&lt;/h2&gt;

&lt;p&gt;Como todo desenvolvedor, nada melhor do que saber como preparar seu ambiente de desenvolvimento com Crystal, não é mesmo? Bem, vamos então navegar por algumas tecnologias que vão te ajudar nessa jornada.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language Server Protocol (LSP)
&lt;/h3&gt;

&lt;p&gt;Como todo bom desenvolvedor, sabemos que um LSP pode nos auxiliar muito durante o desenvolvimento de software, por isso, o LSP que estarei recomendando para uso com Crystal é o &lt;a href="https://github.com/elbywan/crystalline"&gt;Crystalline&lt;/a&gt;, na qual você poderá configurar de forma simples na maioria dos editores de código que esteja utilizando. &lt;/p&gt;

&lt;p&gt;Basicamente o Crystalline vai disponibilizar um executável simples, sendo totalmente escrito em Crystal. Você pode seguir os passos deixados no próprio repositório para configurar seu ambiente, porém, gostaria de dizer que um dos guias de configuração que contribuí foi para o Emacs, utilizando o &lt;a href="https://emacs-lsp.github.io/lsp-mode/tutorials/crystal-guide/"&gt;emacs-lsp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Minhas recomendações para editores de código são bem pessoais, porém, recomendaria alguns como Visual Studio Code, Sublime Text, Vim e Emacs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read-Eval-Print Loop (REPL)
&lt;/h3&gt;

&lt;p&gt;Desenvolver ao lado de um REPL é uma experiência simplesmente magnífica e recomendo sempre que possível, por isso, Crystal não fica de fora no mundo de REPLs e possui o &lt;a href="https://github.com/crystal-community/icr"&gt;icr&lt;/a&gt; como REPL oficial, vindo hoje já embutido no próprio Crystal, podendo ser acessado com o comando &lt;code&gt;crystal i&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Basicamente a funcionalidade principal do REPL é ser seu companheiro durante o desenvolvimento, possibilitando a execução de trechos do código de forma isolada sem muitos problemas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code style linter
&lt;/h3&gt;

&lt;p&gt;Mais importante do que escrever código para si mesmo é escrever código para outras pessoas, por isso, sempre que possível é recomendado escrever códigos de acordo com as convenções de cada linguagem de programação. Dessa forma, Crystal possui uma &lt;a href="https://crystal-lang.org/reference/1.10/conventions/coding_style.html"&gt;convenção de estilo de código&lt;/a&gt; incrível, logo, nada mais justo do que uma ferramenta que te ajude no processo de escrita.&lt;/p&gt;

&lt;p&gt;Assim surge o projeto &lt;a href="https://github.com/crystal-ameba/ameba"&gt;Ameba&lt;/a&gt;, sendo um linter para validar seu código e verificar se está adequado de acordo com as convenções apresentadas oficialmente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugger
&lt;/h3&gt;

&lt;p&gt;Nada melhor do que poder rodar seu código passo por passo para validar problemas e rotinas, não é? Pois bem, o projeto &lt;a href="https://github.com/Sija/debug.cr"&gt;debug&lt;/a&gt; surge com objetivo de ser um debugger completo para seu desenvolvimento, sendo escrito completamente em Crystal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gerenciador de dependências
&lt;/h3&gt;

&lt;p&gt;Dependências podem ser definidas como um conjunto de pacotes/bibliotecas que são necessárias para a execução de determinada aplicação. Gerenciar dependências de forma elegante é algo que Crystal não decepciona utilizando o projeto &lt;a href="https://github.com/crystal-lang/shards"&gt;Shards&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basicamente existe um arquivo chamado &lt;code&gt;shard.yml&lt;/code&gt;, utilizado para definir de maneira simples pontos como nome do projeto, autores, dependências, versão atual e licença em que determinado projeto é distribuído.&lt;/p&gt;

&lt;h3&gt;
  
  
  Livro
&lt;/h3&gt;

&lt;p&gt;Um livro sobre a linguagem é necessário, não apenas para ser utilizado como referência, mas, para ser utilizado no processo de aprendizado do leitor.&lt;/p&gt;

&lt;p&gt;Assim surge o projeto &lt;a href="https://github.com/crystal-lang/crystal-book"&gt;crystal-book&lt;/a&gt;, sendo um livro completo com referências da documentação oficial.&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentação
&lt;/h3&gt;

&lt;p&gt;A documentação oficial é necessária para qualquer tecnologia, assim, Crystal possui dois tipos de documentações que podem ser encontradas, sendo elas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://crystal-lang.org/reference/1.10/index.html"&gt;Documentação do site oficial com o Crystal Book&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://crystal-lang.org/api/1.10.1/"&gt;Documentação de &lt;em&gt;API&lt;/em&gt; da versão atual&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A segunda referência geralmente é utilizada para um detalhamento maior dos métodos e funcionalidades nativas que Crystal proporciona.&lt;/p&gt;

&lt;h3&gt;
  
  
  Patterns
&lt;/h3&gt;

&lt;p&gt;A definição de patterns e padrões de código é necessária, por isso, existe um repositório com exemplos didáticos de implementações com Crystal utilizando os patterns GOF (Gang of Four), chamado &lt;a href="https://github.com/crystal-community/crystal-patterns"&gt;crystal-patterns&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frameworks
&lt;/h2&gt;

&lt;p&gt;Atualmente, Crystal conta com diversos frameworks para diversos propósitos, porém, irei citar os mais conhecidos para desenvolvimento de aplicações web no geral.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kemal
&lt;/h3&gt;

&lt;p&gt;Sendo um dos frameworks mais conhecidos, &lt;a href="https://github.com/kemalcr/kemal"&gt;Kemal&lt;/a&gt; se destaca por ser inspirado no estilo de outro framework já existente para Ruby, o Sinatra, sendo utilizado para ser uma solução simples, com tratamento de rotas elegante, possibilitando um middleware que pode ser ampliado.&lt;/p&gt;

&lt;p&gt;Sua implementação ocorre de forma simples, sendo bem minimalista, assim, uma comparação deixada no &lt;a href="https://kemalcr.com/"&gt;site oficial do Kemal&lt;/a&gt; compara a quantidade de requisições por segundo de uma aplicação com Kemal comparada com uma aplicação Ruby com Sinatra: enquanto o Sinatra conseguiu chegar em 5268 requisições por segundo, Kemal conseguiu atingir invejadas &lt;strong&gt;122697&lt;/strong&gt; requisições por segundo (magnífico, não é?).&lt;/p&gt;

&lt;h3&gt;
  
  
  Amber
&lt;/h3&gt;

&lt;p&gt;Com uma proposta um pouco diferente do Kemal, porém, levando tanto o Kemal quanto Rails e Phoenix como inspiração, temos o &lt;a href="https://github.com/amberframework/amber"&gt;Amber&lt;/a&gt;, um framework para aplicações robustas, possuindo templates de renderização HTML prontos, possibilitando um desenvolvimento mais produtivo.&lt;/p&gt;

&lt;p&gt;O framework conta com a possibilidade de uso de três ORMs distintos, sendo eles &lt;a href="https://github.com/imdrasil/jennifer.cr"&gt;Jennifer&lt;/a&gt;, &lt;a href="https://github.com/amberframework/granite"&gt;Granite&lt;/a&gt; e &lt;a href="https://github.com/Crecto/crecto"&gt;Crecto&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lucky
&lt;/h3&gt;

&lt;p&gt;Sendo um framework inspirado principalmente no Rails, o Lucky é um framework que está no coração de grande parte dos desenvolvedores que alguma vez já trabalharam com Crystal, trazendo infinitas possibilidades, sendo extremamente rápido e produtivo!&lt;/p&gt;

&lt;p&gt;O &lt;a href="https://github.com/luckyframework/lucky"&gt;repositório oficial&lt;/a&gt; está disponível no GitHub, tendo consigo também um artigo interessante falando sobre o uso do Lucky na perspectiva de um desenvolvedor que já trabalhou alguma vez com Rails. O nome do artigo é &lt;a href="https://hackernoon.com/ruby-on-rails-to-lucky-on-crystal-blazing-fast-fewer-bugs-and-even-more-fun-104010913fec"&gt;Ruby on Rails to Lucky on Crystal: Blazing fast, fewer bugs, and even more fun&lt;/a&gt; e recomendo a leitura.&lt;/p&gt;

&lt;h3&gt;
  
  
  Marten
&lt;/h3&gt;

&lt;p&gt;Um framework novo, porém com propostas interessantes, trazendo conceitos novos para o mundo de desenvolvimento com Crystal, ampliando a simplicidade e produtividade dentro do seu código. Este é o &lt;a href="https://github.com/martenframework/marten"&gt;Marten&lt;/a&gt;, tendo seu repositório oficial publicado no GitHub já está tomando espaço e crescendo cada vez mais como um dos frameworks para Crystal que tende a melhorar ainda mais. &lt;/p&gt;

&lt;p&gt;Já ganhou um espaço especial no meu coração e tenho certeza que você vai adorar utilizar o Marten em seu cotidiano como desenvolvedor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projetos com Crystal
&lt;/h2&gt;

&lt;p&gt;Bem, como foi possível observar, a aplicabilidade de Crystal é bem vasta e existem diversas ferramentas para te auxiliar durante todo o processo, mas, quais projetos reais já existem e levam como base o uso de Crystal? Bem, vamos passar citando alguns maneiros se você &lt;em&gt;talvez&lt;/em&gt; esteja pensando em começar a contribuir...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/veelenga/awesome-crystal"&gt;Awesome Crystal&lt;/a&gt;: conjunto de repositórios, bibliotecas e ferramentas para uso no desenvolvimento com Crystal, trazendo tudo de melhor que o ecossistema pode te proporcionar&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/iv-org/invidious"&gt;Invidious&lt;/a&gt;: um projeto que tem crescido muito e traz consigo o objetivo de ser uma alternativa para o front-end do YouTube, reduzindo a quantidade de JavaScript a ser renderizado, sendo distribuído sob licença AGPL 3.0&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/jeromegn/slang"&gt;Slang&lt;/a&gt;: uma linguagem de template inspirada no Slim para construção de páginas web sem a necessidade de escrever HTML puro&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lucaong/immutable"&gt;Immutable&lt;/a&gt;: uma implementação completa de uma coleção de estruturas de dados imutáveis, thread-safe e persistente, possibilitando uma melhor segurança no processamento e acesso de memória&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/vitobotta/hetzner-k3s"&gt;Hetzner k3s&lt;/a&gt;: um CLI completo para gerenciamento de cluster Kubernetes na Hetzner Cloud utilizando a distribuição k3s&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lanjoni/hackacrow"&gt;Hackacrow&lt;/a&gt;: um CLI completo para validação de entradas e saídas de comandos, sendo útil principalmente para validações de respostas em hackathons&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/veelenga/crystal-zsh"&gt;Crystal ZSH&lt;/a&gt;: um plugin completo para utilizar junto do &lt;code&gt;oh-my-zsh&lt;/code&gt;, permitindo uma integração magnífica com seu terminal durante o desenvolvimento com Crystal&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/veelenga/awesome-crystal#editor-plugins"&gt;Editor Plugins&lt;/a&gt;: sendo uma área específica de outro repositório (&lt;code&gt;awesome-crystal&lt;/code&gt; nesse caso) conta com plugins interessantes para diferentes editores de código, por isso, recomendo conhecer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Existem diversos outros projetos com Crystal, porém, acredito que vale a pena conferir o primeiro repositório citado anteriormente para conhecer outros projetos que utilizam Crystal. &lt;/p&gt;

&lt;h2&gt;
  
  
  Finalização
&lt;/h2&gt;

&lt;p&gt;O intuito desse artigo foi apresentar um pouco mais sobre a proposta que Crystal traz no mundo de desenvolvimento de software, citando ferramentas e projetos que podem fazer parte do seu cotidiano de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Se você quer aprender um pouco mais sobre Crystal com um conteúdo totalmente gratuito, em português, escrito com muito amor e carinho, recomendo a leitura do &lt;a href="https://github.com/lanjoni/crystal4noobs"&gt;crystal4noobs&lt;/a&gt;, um conteúdo parte do projeto &lt;a href="https://github.com/he4rt/4noobs"&gt;4noobs&lt;/a&gt; da &lt;a href="https://heartdevs.com/"&gt;He4rt Devs&lt;/a&gt;, trazendo conteúdo de qualidade para todos de forma gratuita.&lt;/p&gt;

&lt;p&gt;Agradeço imensamente se você chegou até aqui e espero que tenha gostado da leitura. Não se esqueça de deixar sua estrelinha os repositórios apresentados. Espero que esse artigo possa &lt;em&gt;crystalizar&lt;/em&gt; ainda mais sua rotina de desenvolvimento. Meu muito obrigado e até a próxima!&lt;/p&gt;

&lt;p&gt;Da comunidade para a comunidade 💜💛&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>ruby</category>
      <category>braziliandevs</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to write a CRUD CLI using Elixir and ScyllaDB</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Mon, 18 Sep 2023 21:30:00 +0000</pubDate>
      <link>https://dev.to/guto/how-to-write-a-crud-cli-using-elixir-and-scylladb-4bek</link>
      <guid>https://dev.to/guto/how-to-write-a-crud-cli-using-elixir-and-scylladb-4bek</guid>
      <description>&lt;p&gt;If you know high traffic applications for communication, applications that need low latency and good fault tolerance, you have most likely already come across the names Elixir (as a programming language) and ScyllaDB (being a database NoSQL aimed at low latency). The objective of both is very similar: to work with applications that generally require greater care for stability.&lt;/p&gt;

&lt;p&gt;ScyllaDB is recognized worldwide as an extremely fast database, being based on Apache Cassandra, bringing several improvements for low latency. Furthermore, ScyllaDB is completely free, open source, and is distributed under the GNU AGPL license.&lt;/p&gt;

&lt;p&gt;Elixir, on the other hand, is a programming language known for dealing very well with the applicability of concepts such as concurrency and fault tolerance and this is thanks to the Erlang ecosystem, which in this case, Elixir makes use of the virtual machine called BEAM, designed specifically to work with high-volume messaging applications.&lt;/p&gt;

&lt;p&gt;The purpose of this article is to offer an introduction to how you can create your first application using both, opening doors and possibilities for your future with development with these two incredible technologies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Starting the project

&lt;ul&gt;
&lt;li&gt;Installing Elixir&lt;/li&gt;
&lt;li&gt;Installing ScyllaDB&lt;/li&gt;
&lt;li&gt;Starting our project&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Configuring the project

&lt;ul&gt;
&lt;li&gt;Defining dependencies&lt;/li&gt;
&lt;li&gt;Configuring .env&lt;/li&gt;
&lt;li&gt;Defining our connection module&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Implementing actions with the database&lt;/li&gt;

&lt;li&gt;

Commands

&lt;ul&gt;
&lt;li&gt;Add&lt;/li&gt;
&lt;li&gt;List&lt;/li&gt;
&lt;li&gt;Delete&lt;/li&gt;
&lt;li&gt;Stress&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Implementing user interaction&lt;/li&gt;

&lt;li&gt;Running our application&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Starting the project
&lt;/h2&gt;

&lt;p&gt;Beforehand we need to install both Elixir and ScyllaDB. I won't go into too much detail about the installation because this makes the article simpler. So let's start with installing Elixir.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing Elixir
&lt;/h3&gt;

&lt;p&gt;To install Elixir in general, there are two main methods: installing directly from your package manager or using a version manager for programming languages. In my case I will be using &lt;code&gt;asdf&lt;/code&gt; as responsible for managing my Elixir versions. If you want to install Elixir using your package manager, click &lt;a href="https://elixir-lang.org/install.html" rel="noopener noreferrer"&gt;here&lt;/a&gt; to receive more information.&lt;/p&gt;

&lt;p&gt;To install &lt;code&gt;asdf&lt;/code&gt; you can check by clicking &lt;a href="https://asdf-vm.com/guide/getting-started.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. As a preference, I always choose to install with "Bash &amp;amp; Git" or "Zsh &amp;amp; Git". Once installed, we will prepare the installation to receive the latest version of Erlang and Elixir in our project. To install Erlang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git

&lt;span class="nv"&gt;$ &lt;/span&gt;asdf &lt;span class="nb"&gt;install &lt;/span&gt;erlang latest

&lt;span class="nv"&gt;$ &lt;/span&gt;asdf global erlang latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Did you have any problems with the installation? Access the &lt;a href="https://github.com/asdf-vm/asdf-erlang" rel="noopener noreferrer"&gt;official guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To install Elixir:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git

&lt;span class="nv"&gt;$ &lt;/span&gt;asdf &lt;span class="nb"&gt;install &lt;/span&gt;elixir latest

&lt;span class="nv"&gt;$ &lt;/span&gt;asdf global elixir latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Did you have any problems with the installation? Access the &lt;a href="https://github.com/asdf-vm/asdf-elixir" rel="noopener noreferrer"&gt;official guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, now that we have both installed we can test to see if everything is ok by typing &lt;code&gt;elixir -v&lt;/code&gt; in our terminal emulator and we will get a response similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Erlang/OTP 25 [erts-13.2.2.2] [source] [64-bit]

Elixir 1.13.4 (compiled with Erlang/OTP 23)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;These are my installed versions for Erlang and Elixir. If you want to install the same versions as me on your machine, just modify the &lt;code&gt;asdf install&lt;/code&gt; command, replacing &lt;code&gt;latest&lt;/code&gt; with the version number and then set it to &lt;code&gt;asdf global elixir 1.13.4&lt;/code&gt; in this case.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Installing ScyllaDB
&lt;/h3&gt;

&lt;p&gt;There are several ways to use ScyllaDB, which you can use with &lt;a href="https://www.scylladb.com/product/scylla-cloud/" rel="noopener noreferrer"&gt;ScyllaDB Cloud&lt;/a&gt;, with ScyllaDB &lt;a href="//https%20://opensource.docs.scylladb.com/stable/getting-started/install-scylla/"&gt;installed on your machine&lt;/a&gt; or the way I will use it: with Docker containers.&lt;/p&gt;

&lt;p&gt;If you don't already have Docker installed, I recommend accessing the [installation] guide (&lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/install/&lt;/a&gt;). If you want to use ScyllaDB Cloud or ScyllaDB installed on your machine, there's no problem, just be careful when placing the node links when initializing and configuring the project, but when we get to this part I'll explain it better.&lt;/p&gt;

&lt;p&gt;Well, continuing... To run our container with ScyllaDB in Docker we will use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; some-scylla &lt;span class="nt"&gt;-p&lt;/span&gt; 9042:9042 &lt;span class="nt"&gt;-d&lt;/span&gt; scylladb/scylla
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-p&lt;/code&gt; option indicates that we want to bind port 9042 of the container with port 9042 of our machine, allowing our container to now be accessed directly on our &lt;code&gt;localhost:9042&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For test the connection, after executing the command, wait a few seconds for everything to start correctly in the container and then type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; some-scylla cqlsh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So you will see a response similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Connected to at 172.17.0.2:9042.
[cqlsh 5.0.1 | Cassandra 3.0.8 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.
cqlsh&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our console where we can execute commands to interact with ScyllaDB. By default, the language used is &lt;a href="https://cassandra.apache.org/doc/latest/cassandra/cql/" rel="noopener noreferrer"&gt;CQL (Cassandra Query Language)&lt;/a&gt;, very similar to the standard database SQL that you probably have already had contact.&lt;/p&gt;

&lt;p&gt;Well, let's run a simple command to describe all the &lt;code&gt;keyspaces&lt;/code&gt; we have in our container. &lt;code&gt;keyspaces&lt;/code&gt; could be defined with a simple analogy: keyspace is basically the same as database when you use a relational database like MySQL or PostgreSQL for example (the definition goes &lt;em&gt;a little beyond that&lt;/em&gt;, but I won't go into it very).&lt;/p&gt;

&lt;p&gt;To describe your &lt;code&gt;keyspaces&lt;/code&gt; run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;cqlsh&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;DESCRIBE&lt;/span&gt; &lt;span class="n"&gt;KEYSPACES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you should see a response similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;system_schema system_traces system_distributed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We haven't created any &lt;code&gt;keyspace&lt;/code&gt; yet, right? Well, let's create our keyspace, which in this case is for a &lt;code&gt;media_player&lt;/code&gt;, with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;cqlsh&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;KEYSPACE&lt;/span&gt; &lt;span class="n"&gt;media_player&lt;/span&gt;
     &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;replication&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'NetworkTopologyStrategy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'replication_factor'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'3'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;durable_writes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let's create the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;cqlsh&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;media_player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;songs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;titletext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;album&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;artist&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="nb"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Starting our project
&lt;/h3&gt;

&lt;p&gt;For start a new project, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mix new media_player
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html" rel="noopener noreferrer"&gt;Mix&lt;/a&gt; is much more than a dependency manager for Elixir, after all, with it we can run and manage our entire project. By default, Mix is already installed together with Elixir.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And a project will be created with the structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── README.md
├── lib
│   └── media_player.ex
├── mix.exs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, now that we have our project initialized, we can start playing, so open your favorite code editor and let's go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring the project
&lt;/h2&gt;

&lt;p&gt;At this point we will configure our project in Elixir to install and use all the tools necessary to build our CLI, in addition to defining the first settings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining dependencies
&lt;/h3&gt;

&lt;p&gt;After opening your code editor, notice that there is a file named &lt;code&gt;mix.exs&lt;/code&gt;. This file is responsible for defining several attributes about our project, including the dependencies that will be used during its development.&lt;/p&gt;

&lt;p&gt;Going down the page a little you will see an area that starts with &lt;code&gt;defp deps do&lt;/code&gt;... Exactly in this part we will modify and insert the following dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Run "mix help deps" to learn about dependencies.&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:dotenv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 3.0"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.0"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:xandra&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 0.14"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:elixir_uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/avdi/dotenv_elixir" rel="noopener noreferrer"&gt;Dotenv&lt;/a&gt;: A port of dotenv to Elixir.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ericmj/decimal" rel="noopener noreferrer"&gt;Decimal&lt;/a&gt;: Arbitrary precision decimal arithmetic.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lexhide/xandra" rel="noopener noreferrer"&gt;Xandra&lt;/a&gt;: Fast, simple, and robust Cassandra/ScyllaDB driver for Elixir.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/zyro/elixir-uuid" rel="noopener noreferrer"&gt;Elixir UUID&lt;/a&gt;: UUID generator and utilities for Elixir. See RFC 4122.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, now that we have our dependencies defined we can run it in our terminal emulator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mix deps.get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The command above will install all dependencies that were defined in our &lt;code&gt;mix.exs&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Great! Now we can configure our environment variables for the project within &lt;code&gt;.env&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring .env
&lt;/h3&gt;

&lt;p&gt;Well, let's now create a file called &lt;code&gt;.env&lt;/code&gt; at the root of our project (that's right, at the same level as our &lt;code&gt;mix.exs&lt;/code&gt;). It will be responsible for defining the first configurations of our project, including the environment variables that will be used to connect our cluster.&lt;/p&gt;

&lt;p&gt;When creating the file and opening it in the code editor, we will define:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SCYLLADB_USERNAME=
SCYLLADB_PASSWORD=
SCYLLADB_NODE=
SCYLLADB_KEYSPACE=
SCYLLADB_TABLE=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SCYLLADB_USERNAME&lt;/code&gt;: username configured to connect to ScyllaDB.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SCYLLADB_PASSWORD&lt;/code&gt;: password configured for the user.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SCYLLADB_NODE&lt;/code&gt;: complete url to connect to our node, you can enter just one url (such as &lt;code&gt;localhost:9042&lt;/code&gt; for example) or define the complete nodes generated separated by a comma (such as &lt;code&gt;scylla-node1.com,scylla- node-2.com,scylla-node-3.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SCYLLADB_KEYSPACE&lt;/code&gt;: the keyspace generated for our application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SCYLLADB_TABLE&lt;/code&gt;: table that will be used for the respective keyspace.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way our .env should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SCYLLADB_USERNAME=scylla
SCYLLADB_PASSWORD=scylla
SCYLLADB_NODE=localhost:9042
SCYLLADB_KEYSPACE=media_player
SCYLLADB_TABLE=songs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect! Now that our connection files are ready, we can start structuring the project, shall we?&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining our connection module
&lt;/h3&gt;

&lt;p&gt;It is elegant and interesting to separate the connection module in a separate area of our project, allowing for more practical maintenance and attractive organization, so let's create two directories with the path &lt;code&gt;lib/media_player/config&lt;/code&gt;. This directory will be responsible for storing two main configuration files: the file for connecting to the Cluster and the file for defining the keyspace and table.&lt;/p&gt;

&lt;p&gt;Well, let's create two files inside the &lt;code&gt;lib/media_player/config&lt;/code&gt; directory, called &lt;code&gt;connection.ex&lt;/code&gt; and &lt;code&gt;database.ex&lt;/code&gt;. This way our directory structure will now be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── README.md
├── lib
│   ├── media_player
│   │   └── config
│   │   ├── connection.ex
│   │   └── database.ex
│   └── media_player.ex
├── mix.exs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Yes, I omitted the &lt;code&gt;deps&lt;/code&gt; directory because it contains the dependencies, that is, nothing that we are going to modify manually, don't worry, in addition to omitting the &lt;code&gt;test&lt;/code&gt; directory because it will contain the tests that can be implemented, but, no let's implement it for now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, now we can define the connection to our cluster, starting with the &lt;code&gt;database.ex&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Database&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Dotenv&lt;/span&gt;

  &lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SCYLLADB_USERNAME"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SCYLLADB_PASSWORD"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="no"&gt;Xandra&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="ss"&gt;sync_connect:&lt;/span&gt; &lt;span class="ss"&gt;:infinity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;authentication:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Xandra&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Authenticator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="ss"&gt;nodes:&lt;/span&gt;
          &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SCYLLADB_NODE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;cluster&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this file we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We import the &lt;code&gt;Dotenv&lt;/code&gt; library to manage the variables defined in our &lt;code&gt;.env&lt;/code&gt; file;&lt;/li&gt;
&lt;li&gt;We load the variables with the &lt;code&gt;load()&lt;/code&gt; function that comes from the &lt;code&gt;Dotenv&lt;/code&gt; library;&lt;/li&gt;
&lt;li&gt;We created a function named &lt;code&gt;start_link&lt;/code&gt; that will be responsible for starting the connection link with our cluster;&lt;/li&gt;
&lt;li&gt;In the function we define the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; receiving these values from the &lt;code&gt;.env&lt;/code&gt; file;&lt;/li&gt;
&lt;li&gt;We initialize the cluster with the function coming from &lt;code&gt;Xandra&lt;/code&gt; with the name &lt;code&gt;Xandra.Cluster.start_link&lt;/code&gt;, responsible for starting a connection link with the cluster

&lt;ul&gt;
&lt;li&gt;In this function we define that &lt;code&gt;sync_connect&lt;/code&gt; is with value &lt;code&gt;:infinity&lt;/code&gt;! This means that it will try to make the connection with an infinite expected response time (that is, the module will wait as long as necessary to make the complete connection of all nodes). To read more about click &lt;a href="https://hexdocs.pm/xandra/Xandra.Cluster.html#start_link/1" rel="noopener noreferrer"&gt;here&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;We define that we are going to perform authentication and pass &lt;code&gt;options&lt;/code&gt; (which was defined previously) as a parameter;&lt;/li&gt;
&lt;li&gt;We define our nodes by loading from our &lt;code&gt;.env&lt;/code&gt; file and performing a division with the commas found, distributing them in a list (&lt;code&gt;nodes&lt;/code&gt; expects a list of urls to make the connection, which is why the split is necessary to create this list) . If you use ScyllaDB Cloud, this is what will make everything work perfectly;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;We return the cluster with the connection ready.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Perfect! Our connection file is ready. Now let's configure a simple area that will only be responsible for returning the keyspace and the table, called &lt;code&gt;connection.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Connection&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Dotenv&lt;/span&gt;

  &lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SCYLLADB_KEYSPACE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SCYLLADB_TABLE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically the only functionality of this module is to have two functions to return the keyspace and the table that we will be using, without the need to always use the &lt;code&gt;.env&lt;/code&gt; library!&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing actions with the database
&lt;/h2&gt;

&lt;p&gt;Well, now is another important point: as our project will have commands, therefore, it would be interesting to create a specific module to handle these commands, right? Perfect! However, before that, what do you think about creating a module to execute queries in the database, so we can centralize where the queries will be executed.&lt;/p&gt;

&lt;p&gt;Well, this is the time to create a file in &lt;code&gt;lib/media_player&lt;/code&gt; with the name &lt;code&gt;actions.ex&lt;/code&gt;. So our directory structure will 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;.
├── README.md
├── lib
│   ├── media_player
│   │   ├── actions.ex
│   │   └── config
│   │   ├── connection.ex
│   │   └── database.ex
│   └── media_player.ex
├── mix.exs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wonder! With the file created we can now create two specific functions, but why two? Simple: the &lt;code&gt;Xandra.Cluster.execute&lt;/code&gt; function has two variations, the first with two parameters (the cluster and the query to be executed) and the second with three parameters (the cluster, the query to be executed and the parameters, being a list that is mainly used to prepare our query).&lt;/p&gt;

&lt;p&gt;Let's go then, our module should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Actions&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;run_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Xandra&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;run_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;prepared&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Xandra&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prepare!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Xandra&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;prepared&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this file we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We define a local &lt;code&gt;cluster&lt;/code&gt; function that does nothing more than initialize and return the connection link to the cluster;&lt;/li&gt;
&lt;li&gt;We define a function &lt;code&gt;run_query/1&lt;/code&gt; that takes just one parameter (being just the query, after all, the cluster is already a local function and we know that we will always execute actions on it);

&lt;ul&gt;
&lt;li&gt;We tried to perform the query with the function &lt;code&gt;Xandra.Cluster.execute&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;If the return is &lt;code&gt;:ok&lt;/code&gt;, it means that everything went well, then we return the complete result (a complete map of the query);&lt;/li&gt;
&lt;li&gt;If the return is &lt;code&gt;:error&lt;/code&gt; it means that an error occurred when performing the query, then we inspect the specific error;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;An important detail is about the assignment made with &lt;code&gt;{:ok, result}&lt;/code&gt; and &lt;code&gt;{:error, error}&lt;/code&gt;, since in Elixir everything has a return, always being a map starting with an atom validating the return type that was given (I recommend seeing more about &lt;a href="https://elixir-lang.org/getting-started/basic-types.html#atoms" rel="noopener noreferrer"&gt;atoms&lt;/a&gt;), so we bind values with a map!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;We define a function &lt;code&gt;run_query/2&lt;/code&gt; that takes two parameters (only the query and the parameters to be executed):

&lt;ul&gt;
&lt;li&gt;We tried to perform the query with the &lt;code&gt;Xandra.Cluster.execute&lt;/code&gt; function:&lt;/li&gt;
&lt;li&gt;If the return is &lt;code&gt;:ok&lt;/code&gt;, it means that everything went well, then we return the complete result (a complete map of the query);&lt;/li&gt;
&lt;li&gt;If the return is &lt;code&gt;:error&lt;/code&gt; it means that an error occurred when performing the query, then we inspect the specific error;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;If you want to see more about how the &lt;code&gt;Xandra.Cluster.execute&lt;/code&gt; function works, click &lt;a href="https://hexdocs.pm/xandra/Xandra.Cluster.html#execute/3" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A detail that you may not have noticed: both functions have the same name, however, they differ in terms of the number of parameters! This makes the magic happen with Elixir. Functions are defined along with the number of parameters they expect to receive, so I put the name of the function followed by a slash "/" with the number of parameters. If you want to know more about it, click &lt;a href="https://elixirschool.com/en/lessons/basics/functions/#functions-and-pattern-matching-4" rel="noopener noreferrer"&gt;here&lt;/a&gt; to better understand how Elixir works with Pattern Matching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commands
&lt;/h2&gt;

&lt;p&gt;Well, now is the long-awaited moment: adding the functions responsible for executing commands in our application! To do this, we will create a file in &lt;code&gt;lib/media_player&lt;/code&gt; with the name &lt;code&gt;commands.ex&lt;/code&gt;. This way our directory structure will be equal to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── README.md
├── lib
│   ├── media_player
│   │   ├── actions.ex
│   │   ├── commands.ex
│   │   └── config
│   │   ├── connection.ex
│   │   └── database.ex
│   └── media_player.ex
├── mix.exs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start by creating the basis of our entire module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Commands&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as:&lt;/span&gt; &lt;span class="no"&gt;Actions&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as:&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically above we defined that we will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The alias &lt;code&gt;Actions&lt;/code&gt; to refer to the &lt;code&gt;MediaPlayer.Actions&lt;/code&gt; module;&lt;/li&gt;
&lt;li&gt;The alias &lt;code&gt;Connection&lt;/code&gt; to refer to the &lt;code&gt;MediaPlayer.Config.Connection&lt;/code&gt; module;&lt;/li&gt;
&lt;li&gt;The private function &lt;code&gt;keyspace&lt;/code&gt; that returns the keyspace value that we will use;&lt;/li&gt;
&lt;li&gt;The private function &lt;code&gt;table&lt;/code&gt; that returns the table value that we will use;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, now we can start implementing the commands, shall we?&lt;/p&gt;

&lt;h3&gt;
  
  
  Add
&lt;/h3&gt;

&lt;p&gt;Well, this command will be used to add songs to our database. Therefore, we will separate it into two main functions, namely &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;add_from&lt;/code&gt;, which receive four parameters to be executed. The &lt;code&gt;add&lt;/code&gt; function will only collect the data to be inserted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Commands&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as:&lt;/span&gt; &lt;span class="no"&gt;Actions&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as:&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;add_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="s2"&gt;"INSERT INTO &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (id, title, album, artist, created_at) VALUES (?, ?, ?, ?, ?);"&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_iso8601&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"T00:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Song added!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Enter the title of the song: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;album&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Enter the album of the song: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;artist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Enter the artist of the song: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Enter the date the song was created (YYYY-MM-DD): "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;add_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, both functions are very specific, so let’s give an example of each one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;add&lt;/code&gt; function will:

&lt;ul&gt;
&lt;li&gt;Collect the song title;&lt;/li&gt;
&lt;li&gt;Collect the music album;&lt;/li&gt;
&lt;li&gt;Collect the song artist;&lt;/li&gt;
&lt;li&gt;Collect the creation date of the song;&lt;/li&gt;
&lt;li&gt;Invoke the &lt;code&gt;add_from&lt;/code&gt; function passing the collected values as parameters;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;The &lt;code&gt;add_from/4&lt;/code&gt; function will:

&lt;ul&gt;
&lt;li&gt;Receive four parameters;&lt;/li&gt;
&lt;li&gt;Create the &lt;code&gt;query&lt;/code&gt; that will be executed;&lt;/li&gt;
&lt;li&gt;Convert the date format to ensure bind compatibility with Xandra;&lt;/li&gt;
&lt;li&gt;Call the function to perform the query passing two parameters: the query and additional options in a list format (as explained previously)&lt;/li&gt;
&lt;li&gt;Then just show the message on the screen when the song is inserted!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Another point: the "|&amp;gt;" pipe in Elixir works like the "|" pipe of Unix shells, being used to pass the return of a function as the first parameter of the next. Read more about pipes &lt;a href="https://elixirschool.com/en/lessons/basics/pipe_operator" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Well, now we have the function responsible for adding a created song! Let's go next time?&lt;/p&gt;

&lt;h3&gt;
  
  
  List
&lt;/h3&gt;

&lt;p&gt;Now let's create a function responsible for listing all the songs we have added. Therefore, we will have as a result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SELECT id, title, album, artist, created_at FROM &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;

    &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
                      &lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"title"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"album"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"artist"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"created_at"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s2"&gt;"ID: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | Title: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | Album: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | Artist: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | Created At: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;list&lt;/code&gt; function does not receive any parameters, after all, it will print the songs that were added to the screen, like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We define a query by selecting &lt;code&gt;id, title, album, artist, created_at&lt;/code&gt; and to define the &lt;code&gt;keyspace&lt;/code&gt; and &lt;code&gt;table&lt;/code&gt; remember that we already have two functions that return these values!&lt;/li&gt;
&lt;li&gt;We tried to perform a simple query (which has no additional options besides &lt;code&gt;query&lt;/code&gt;) and its return we passed to an &lt;code&gt;Enum.each&lt;/code&gt; (similar to a &lt;code&gt;foreach&lt;/code&gt; in other programming languages);

&lt;ul&gt;
&lt;li&gt;Within each we pass an anonymous function responsible for handling the return, which in this case expects to receive a map with the respective fields that were selected;&lt;/li&gt;
&lt;li&gt;We print specific values;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;In the end this will be our return;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;An important detail: in this case, &lt;code&gt;run_query&lt;/code&gt; would return more than one value if we had multiple rows inserted, right? Well, &lt;code&gt;run_query&lt;/code&gt; returns a complete list of maps with their respective values, so we use &lt;code&gt;Enum.each&lt;/code&gt; to treat each index in the list we have.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete
&lt;/h3&gt;

&lt;p&gt;Well, the &lt;code&gt;delete&lt;/code&gt; command is a little more complex because we need the user to type the index he wants to delete, validating it against the list of indexes that were returned! Therefore, the implemented function would result in something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SELECT id, title, album, artist, created_at FROM &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;

    &lt;span class="n"&gt;songs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
                              &lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="s2"&gt;"title"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="s2"&gt;"album"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="s2"&gt;"artist"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="s2"&gt;"created_at"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;
                            &lt;span class="p"&gt;},&lt;/span&gt;
                            &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s2"&gt;"Index: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | Title: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | Album: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | Artist: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | Created At: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;album:&lt;/span&gt; &lt;span class="n"&gt;album&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;artist:&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;created_at:&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Enter the index of the song you want to delete: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;songs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;%{}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;song&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"DELETE FROM &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; WHERE id = ? AND created_at = ?;"&lt;/span&gt;

        &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;song&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;song&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Song deleted!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Invalid index."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, basically we have in this function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Definition of the &lt;code&gt;query&lt;/code&gt; returning all added songs;&lt;/li&gt;
&lt;li&gt;Listing similar to the previously implemented &lt;code&gt;list&lt;/code&gt; function;

&lt;ul&gt;
&lt;li&gt;We try to perform the query in &lt;code&gt;Actions.run_query&lt;/code&gt; and pass it to &lt;code&gt;Enum.with_index&lt;/code&gt; to have the indexes;&lt;/li&gt;
&lt;li&gt;This time instead of presenting the &lt;code&gt;id&lt;/code&gt; of the song we present a manual index (instead of starting with 0 it starts with 1, hence &lt;code&gt;index + 1&lt;/code&gt;), in which the user will type (more practical to type a number integer than a UUID isn't it?);&lt;/li&gt;
&lt;li&gt;We print the values;&lt;/li&gt;
&lt;li&gt;We added the complete list in &lt;code&gt;songs&lt;/code&gt;;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;We wait for the user to make an entry stating which index he wants to delete and we parse the entry that will be saved in &lt;code&gt;input&lt;/code&gt;;&lt;/li&gt;

&lt;li&gt;We check whether the index entered is present in &lt;code&gt;songs&lt;/code&gt;;

&lt;ul&gt;
&lt;li&gt;If you are:&lt;/li&gt;
&lt;li&gt;We create the query;&lt;/li&gt;
&lt;li&gt;We tried to perform the query in &lt;code&gt;Actions.run_query&lt;/code&gt; and added the list of options to bind to the query as a parameter;&lt;/li&gt;
&lt;li&gt;We print the message informing that the song has been deleted;&lt;/li&gt;
&lt;li&gt;If not:&lt;/li&gt;
&lt;li&gt;We print that the index is invalid&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This way we finish our function to delete a song!&lt;/p&gt;

&lt;h3&gt;
  
  
  Stress
&lt;/h3&gt;

&lt;p&gt;Great! The commands that necessarily manipulate user input are finished! Now let's create an additional command that will be responsible for performing a stress test on our database. We will define two functions, namely the &lt;code&gt;stress&lt;/code&gt; function that will initialize the command, in addition to a private function with the name &lt;code&gt;generate_stress_query&lt;/code&gt; that receives a parameter with the name &lt;code&gt;some_id&lt;/code&gt;, with the index being inserted.&lt;/p&gt;

&lt;p&gt;First of all, we must add the following section at the beginning of our module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Commands&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Task&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;Task&lt;/code&gt; we can perform asynchronous calls with better practicality and performance. To read more click &lt;a href="https://hexdocs.pm/elixir/1.12/Task.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thus, implementing our functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;generate_stress_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;current_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_today&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="s2"&gt;"INSERT INTO &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;keyspace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (
      id, title, album, artist, created_at
    ) VALUES (
      &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,
      'Test Song &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;',
      'Test Artist &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;',
      'Test Album &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;some_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;',
      '&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;current_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'
    );"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;stress&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;cluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Simple stress test&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;100_000&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] Adding seed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="no"&gt;Xandra&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generate_stress_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;max_concurrency:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Time taken: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc_now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;stress&lt;/code&gt; function:

&lt;ul&gt;
&lt;li&gt;Mark the start time of the function with &lt;code&gt;Time.utc_now()&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Initializes the cluster manually for better performance and handling.&lt;/li&gt;
&lt;li&gt;We initiate a call from 1 to 100000 that goes asynchronously:&lt;/li&gt;
&lt;li&gt;Define an anonymous function that receives an &lt;code&gt;id&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;We print that we are adding a certain index;&lt;/li&gt;
&lt;li&gt;We tried to perform the query with &lt;code&gt;Xandra.Cluster.execute&lt;/code&gt; by calling the &lt;code&gt;generate_stress_query&lt;/code&gt; function, responsible for generating a complete query with the &lt;code&gt;id&lt;/code&gt; provided;&lt;/li&gt;
&lt;li&gt;We set a &lt;code&gt;max_concurrency&lt;/code&gt; of 500 to limit the number of asynchronous calls;&lt;/li&gt;
&lt;li&gt;We format it into a list;&lt;/li&gt;
&lt;li&gt;We print the time spent to carry out the entire test, calculating the difference between the current time and the start time in seconds;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;generate_stress_query&lt;/code&gt; function:

&lt;ul&gt;
&lt;li&gt;Receives an &lt;code&gt;id&lt;/code&gt; as a parameter to generate the query;&lt;/li&gt;
&lt;li&gt;Sets the current date to insert;&lt;/li&gt;
&lt;li&gt;Returns the complete query already formatted;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Well, that way our functions for the stress test are ready! Now we must implement the command inputs that a user can enter!&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing user interaction
&lt;/h2&gt;

&lt;p&gt;Let's modify our main module, &lt;code&gt;MediaPlayer&lt;/code&gt; in the &lt;code&gt;media_player.ex&lt;/code&gt; file! Well, first let's define an alias for the commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;MediaPlayer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as:&lt;/span&gt; &lt;span class="no"&gt;Commands&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The alias will be used to refer to the &lt;code&gt;MediaPlayer.Commands&lt;/code&gt; module!&lt;/p&gt;

&lt;p&gt;The first function we will implement is &lt;code&gt;loop&lt;/code&gt;, which will be responsible for directing the commands, receiving user input and remaining in an infinite loop always waiting for input, see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-------------------------------------"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Type any command: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="s2"&gt;"!add"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Commands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="s2"&gt;"!list"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Commands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="s2"&gt;"!delete"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Commands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="s2"&gt;"!stress"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Commands&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stress&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="s2"&gt;"exit"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Bye bye!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="ss"&gt;:OK&lt;/span&gt;

      &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Command not found!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically we wait for user input with a command and enter a &lt;code&gt;case&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;!add&lt;/code&gt; invokes the &lt;code&gt;Commands.add()&lt;/code&gt; function;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;!list&lt;/code&gt; invokes the &lt;code&gt;Commands.list()&lt;/code&gt; function;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;!delete&lt;/code&gt; invokes the &lt;code&gt;Commands.delete()&lt;/code&gt; function;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;!stress&lt;/code&gt; invokes the &lt;code&gt;Commands.stress()&lt;/code&gt; function;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exit&lt;/code&gt; prints a goodbye message and returns &lt;code&gt;:ok&lt;/code&gt;, defining that the function no longer enters a recursive loop, ending our application;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_&lt;/code&gt; prints a command not found message and enters a recursive loop, waiting for new input;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, now we have our main function ready! But how are we going to execute it? Simple, let's create a &lt;code&gt;start&lt;/code&gt; function that will be responsible for starting our application, in addition to a &lt;code&gt;run&lt;/code&gt; function, which will be the function invoked by the initial &lt;code&gt;start&lt;/code&gt; function, see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-------------------------------------"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"- ScyllaDB Cloud Elixir Media Player -"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"- Leave a star on the repo -"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-------------------------------------"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Here some possibilities"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" !add - add new song"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" !list - list all songs"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" !delete - delete a specific song"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" !stress - stress testing with mocked data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-------------------------------------"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;start&lt;/code&gt; function:

&lt;ul&gt;
&lt;li&gt;It receives two parameters, but we will not use them, so we define them as &lt;code&gt;_&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Invokes the &lt;code&gt;run&lt;/code&gt; function;&lt;/li&gt;
&lt;li&gt;Returns &lt;code&gt;{:ok, self()}&lt;/code&gt; to define that the function was executed successfully, closing our application;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;run&lt;/code&gt; function:

&lt;ul&gt;
&lt;li&gt;Print a welcome message;&lt;/li&gt;
&lt;li&gt;Prints a message with command possibilities;&lt;/li&gt;
&lt;li&gt;Invokes the &lt;code&gt;loop&lt;/code&gt; function to start the infinite loop;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This concludes our complete application! Now are we going to execute it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Running our application
&lt;/h2&gt;

&lt;p&gt;Well, now that we have our application ready, let's execute the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mix run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way we can start interacting with the application!&lt;/p&gt;

&lt;p&gt;See a demo of the project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/608562" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fasciinema.org%2Fa%2F608562.svg" alt="asciicast"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Thank you very much if you read this far! The purpose of this article was to demonstrate how we can use ScyllaDB with Elixir, making a simple demonstration using Xandra as responsible for the connection between the two. I highly recommend following content from &lt;a href="https://university.scylladb.com/" rel="noopener noreferrer"&gt;ScyllaDB University&lt;/a&gt; for more quality educational content, as well as seeing articles about using ScyllaDB in general with &lt;a href="https://dev.to/danielhe4rt"&gt;DanielHe4rt&lt;/a&gt; and &lt;a href="https://dev.to/cherryramatis"&gt;Cherry Ramatis&lt;/a&gt;! Both are always contributing and publishing magnificent content.&lt;/p&gt;

&lt;p&gt;I also recommend getting to know the project &lt;a href="https://github.com/scylladb/scylla-cloud-getting-started" rel="noopener noreferrer"&gt;Getting Started with ScyllaDB Cloud&lt;/a&gt; which demonstrates the use of ScyllaDB in general, but, delving a little deeper into the use of ScyllaDB's own platform for managing your Cloud clusters, cool isn't it?&lt;/p&gt;

&lt;p&gt;In the same repository you can access the project using Elixir too, so if you want to see the complete source code, know that it is at the same link mentioned above!&lt;/p&gt;

&lt;p&gt;I hope you enjoyed the content and I hope it clarified the use of ScyllaDB with Elixir. I also hope that you are even more interested in receiving more content like this or learning even more about Elixir. Thank you very much, and see you next time!&lt;/p&gt;

</description>
      <category>scylladb</category>
      <category>elixir</category>
      <category>opensource</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Open Source e Software Livre: conheça e entenda de uma vez por todas o que cada um significa</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Tue, 29 Aug 2023 00:31:08 +0000</pubDate>
      <link>https://dev.to/he4rt/open-source-e-software-livre-conheca-e-entenda-de-uma-vez-por-todas-o-que-cada-um-significa-15in</link>
      <guid>https://dev.to/he4rt/open-source-e-software-livre-conheca-e-entenda-de-uma-vez-por-todas-o-que-cada-um-significa-15in</guid>
      <description>

&lt;h2&gt;
  
  
  Índice
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introdução&lt;/li&gt;
&lt;li&gt;
História

&lt;ol&gt;
&lt;li&gt;O início&lt;/li&gt;
&lt;li&gt;Unix&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Software Livre&lt;/li&gt;

&lt;li&gt;

Open Source

&lt;ol&gt;
&lt;li&gt;Incentivos&lt;/li&gt;
&lt;li&gt;Valores&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

Definições

&lt;ol&gt;
&lt;li&gt;Software Proprietário&lt;/li&gt;
&lt;li&gt;Software Livre X Open Source&lt;/li&gt;
&lt;li&gt;Licenças&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Finalização&lt;/li&gt;

&lt;/ol&gt;




&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;O intuito deste artigo é apresentar os conceitos, história e tudo que temos por trás do mundo do Software Livre e mundo de projetos de código aberto (chamados de projetos Open-Source - nome bem sugestivo).&lt;/p&gt;

&lt;p&gt;Ao finalizar a leitura, você conseguirá entender a diferença dos dois termos e vai ainda poder se aprofundar em seus fundamentos! Não se acanhe, caso tenha alguma dúvida fique livre para perguntar! Aqui é um espaço seguro para ensino e aprendizado.&lt;/p&gt;

&lt;h2&gt;
  
  
  História
&lt;/h2&gt;

&lt;p&gt;Em algum momento tenho certeza que você já se deparou com algum projeto de código aberto, isso mesmo, aqueles que podemos ver o código-fonte e entender todo o seu funcionamento, podendo ainda realizar modificações sobre ele de acordo com sua necessidade... Bem, esses pontos sobre poder ou não poder fazer alguma coisa vamos tratar em breve, mas, por agora entenda que é um projeto que possui o código (em alguma tecnologia específica) aberto ao público geral.&lt;/p&gt;

&lt;p&gt;O direito de ter acesso ao código-fonte de algo vem de muito antes da computação moderna, surgindo principalmente com outros nomes e outras associações (um exemplo de forma similar seria o funcionamento de patentes), com casos datados do início do século XX, como por exemplo o caso &lt;a href="https://automotivehistory.org/september-15-1909-henry-ford-loses-legal-fight-of-a-lifetime-files-appeal/" rel="noopener noreferrer"&gt;Henry Ford de 1909&lt;/a&gt;, na qual houve compartilhamento de dados e informações sobre motores vazados, afinal, entramos no âmbito judicial relacionado aos direitos de uso. &lt;/p&gt;

&lt;p&gt;No final das contas não sou do ramo de direito, sou apenas um entusiasta de projetos de código-aberto e software livre no geral, por isso, vamos passar para os tópicos que já remetem o início da computação com casos da IBM.&lt;/p&gt;

&lt;h3&gt;
  
  
  O início
&lt;/h3&gt;

&lt;p&gt;Voltando para as décadas de 1950 e 1960 temos um mundo totalmente diferente do que vivemos hoje com relação ao uso de software. Naquela época, era comum que houvesse compartilhamento de códigos entre pessoas e empresas, incluindo a própria IBM na jogada. Sistemas operacionais e programas eram comumente distribuídos em conjunto com softwares. Um curioso fato é o nascimento do grupo de usuários &lt;a href="https://www.share.org/" rel="noopener noreferrer"&gt;SHARE&lt;/a&gt; que surgiu em 1955 com objetivo de facilitar o aprendizado e distribuição de software no mundo, realizando compartilhamento de tudo sobre tecnologia na época.&lt;/p&gt;

&lt;p&gt;Em 1969 o RFC (Request for Comments e futuramente se tornando ARPANET) foi publicado, sendo o passo inicial para o que teríamos como Internet posteriormente. Ainda na mesma época temos três pessoas que foram responsáveis pelo início de um projeto que até hoje possui influência tremenda no mundo do uso de softwares no geral, estamos falando de Brian Bernighan, Ken Thompson e Dennis Ritchie, responsáveis por desenvolver uma versão modificada do MULTICS, sendo batizada como UNICS e depois Unix (já ouviu falar desse nome alguma vez?), um &lt;strong&gt;sistema operacional multitarefas e multiusuários&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Em 1970 a IBM (a maior vendedora e produtora de computadores de grande porte da época) que antes vendia seus softwares em conjunto com os hardwares comprados começou a vender softwares separados, trazendo o conceito do software sendo vendido simlesmente como um "produto de prateleira". Bem, o motivo para essa mudança se deu com a evolução constante de sistemas operacionais e compiladores, elevando o custo de produção para um software.&lt;/p&gt;

&lt;p&gt;Ainda no mesmo ano a IBM realiza a compra do chamado ARPANET, iniciando um processo de monopolização na indústria de tecnologia no geral, que antes já era controlada por ela.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unix
&lt;/h3&gt;

&lt;p&gt;Anos mais tarde, em 1972, Brian Bernighan, Ken Thompson e Dennis Ritchie começaram a investir um tempo ainda maior para o desenvolvimento do Unix, com isso, algumas criações foram surgindo como por exemplo a linguagem de programação C, uma melhoria voltada para a performance da linguagem de programação B. Sim, isso mesmo que você ouviu, eles estavam tentando reescrever o Unix em B e a performance não estava das melhores, então eles pensaram "poderíamos criar uma linguagem de programação para resolver nosso problema", e então criaram. Acredito que uma grande maioria das pessoas que estejam lendo isso já tenham escrito ou visto algum código em C... Pois bem, assim foi o seu surgimento.&lt;/p&gt;

&lt;p&gt;Em 1973 surge o chamado Unix BSD com a chegada do Unix na Universidade de Berkeley, na qual tivemos uma alavancada tremenda com o seu desenvolvimento. Com a universidade em crescimento, diversas pessoas puderam se beneficiar do compartilhamento de estudos voltados para seu desenvolvimento, resultando em um processo de comunicação incrível entre pessoas externas, alunos, professores, contribuindo para a expansão do Unix.&lt;/p&gt;

&lt;p&gt;Em 1979 a AT&amp;amp;T começa a forçar licenças restritivas ao decidir que poderia lucrar com o sistema Unix, fazendo com que em 1980 surgissem os primeiros movimentos organizados em busca do que chamamos de Software Livre. Ah, apenas para finalizar este tópico, em 1981 a IBM fechou acordo com a Microsoft para fornecimento do DOS para PC, ainda desconsiderando sua evolução &lt;strong&gt;abriu mão dos direitos autorais do DOS&lt;/strong&gt;, fazendo com que a Microsoft pudesse se expandir futuramente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Software Livre
&lt;/h2&gt;

&lt;p&gt;Richard Stallman publicou uma mensagem no grupo "net.unix-wizards" em 1983 com o assunto "New Unix implementation", anunciando a criação do projeto GNU (um acrônimo para "&lt;strong&gt;G&lt;/strong&gt;NU's &lt;strong&gt;N&lt;/strong&gt;ot &lt;strong&gt;U&lt;/strong&gt;nix"), declarando a necessidade da criação de um "novo Unix", mencionando a necessidade de diversas ferramentas, por isso, pedindo o apoio em contribuições. Podemos dizer que publicamente este foi a primeira declaração de Richard Stallman sobre o início de contribuições públicas para o começo do que seria um sistema operacional amplamente utilizado. As ferramentas que ele cita seriam programas para fazer com que um computador pudesse ser utilizável, incluindo tudo que você imaginar.&lt;/p&gt;

&lt;p&gt;Bem, em 1984 Richard Stallman pediu demissão do AI Lab do MIT, se dedicando completamente ao &lt;a href="https://www.gnu.org/" rel="noopener noreferrer"&gt;Projeto GNU&lt;/a&gt;, publicando o Manifesto GNU (que cita o termo "software livre"). O primeiro software a ser publicado pelo Projeto GNU foi o chamado &lt;a href="https://www.gnu.org/software/emacs/" rel="noopener noreferrer"&gt;GNU Emacs&lt;/a&gt; (que também é hoje meu principal editor de código e textos no geral), escrito por Richard Stallman e Guy L. Steele.&lt;/p&gt;

&lt;p&gt;Em 1985 o sistema de janelas X foi distribuído como software livre pleo Consórcio X (acredito que você também já deva ter ouvido falar sobre o sistema de janelas X), seguindo da fundação da &lt;a href="https://www.fsf.org/" rel="noopener noreferrer"&gt;Free Software Foundation&lt;/a&gt; e a publicação das chamadas "Quatro Liberdades de um Software Livre", sendo elas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Liberdade 0: Liberdade de &lt;strong&gt;executar&lt;/strong&gt; o programa como você desejar, para qualquer propósito;&lt;/li&gt;
&lt;li&gt;Liberdade 1: Liberdade de &lt;strong&gt;estudar&lt;/strong&gt; como o programa funciona e adaptá-lo às suas necessidades (para isso o acesso ao código-fonte é essencial);&lt;/li&gt;
&lt;li&gt;Liberdade 2: Liberdade de &lt;strong&gt;redistribuir cópias&lt;/strong&gt; de modo que você possa ajudar outros;&lt;/li&gt;
&lt;li&gt;Liberdade 3: Liberdade de &lt;strong&gt;redistribuir cópias de suas versões modificadas&lt;/strong&gt;, dando a comunidade a chance de se beneficiar de suas mudanças (acesso ao código-fonte também é essencial);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ainda em 1985 surge o GCC (GNU Compiler Collection - tenho certeza que você também já viu esse nome em algum lugar), escrito inicialmente por Richard Stallman e Len Towe. Toda a definição oficial do que é um software livre pode ser acessada clicando &lt;a href="https://www.gnu.org/philosophy/free-sw.pt-br.html" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Em 1987 Andrew Tanenbaum escreveu uma versão modificada do Unix para fins didáticos, denominada MINIX (sendo posteriormente utilizada como inspiração para o nascimento do kernel Linux).&lt;/p&gt;

&lt;p&gt;Em 1989 a Free Software Foundation criou o conceito de "copyleft" (o contrário de "copyright") e a licença GNU GPL (General Public License) que garantia as quatro liberdades de um software. Seu funcionamento se caracteriza em que eu declaro que um determinado software pertence a X, e este X não permite qualquer venda do software respeitando as quatro liberdades, amarrando o software garantindo o cumprimento das liberdades. Ainda no mesmo ano tivemos o surgimento de outros projetos Software Livre como por exemplo o PostgreSQL lançado por Michael Stonebreaker, Cygnus fundada por Michael Tiemann, David Henkel-Wallace e John Gilmore) se tornou a primeira empresa que essencialmente começou a prover serviços para software livre, entre outros.&lt;/p&gt;

&lt;p&gt;O kernel Linux foi iniciado em 1991 por um estudante filandês da Universidade de Helsinki chamado Linus Torvalds, que anunciou o início do projeto sendo distribuído sob licença GNU GPL, fornecendo a peça final do primeiro sistema operacional completamente livre, o chamado GNU/Linux. Na época Torvalds disse que não queria dinheiro por uma série de razões, mas, que seu principal intuito era pelo sentimento de que estava "seguindo os passos de centenas de cientistas e acadêmicos", afinal, as pessoas construíram seu trabalho "apoiando-se nos ombros de gigantes".&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source
&lt;/h2&gt;

&lt;p&gt;Bem, o termo Software Livre não remete ao software ser gratuito ou não, mas, sobre liberdade (em inglês o nome fica como Free Sofware por isso a confusão era maior), por isso, quando falamos de um software de código-fonte aberto não estamos necessariamente falando de um Software Livre. Desta forma, o termo "open source" surgiu com o intuito de separar estes dois conceitos, criado por &lt;a href="https://opensource.com/article/18/2/coining-term-open-source-software?extIdCarryOver=true&amp;amp;sc_cid=701f2000001OH7EAAW" rel="noopener noreferrer"&gt;Christine Peterson&lt;/a&gt;. A proposta de substituição e uso do termo surgiu partiu dela, especialmente pelo simples fato de seu trabalho estar interligado com o incentivo de práticas de sofwares open source em mercados maiores.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incentivos
&lt;/h3&gt;

&lt;p&gt;O grupo que Christine trabalhava queria mostrar ao mundo que o software ficava melhor quando era compartilhado, colaborativo, aberto e modificável, abrindo diversas possibilidades para seu uso de forma inovadora e criativa, aumentando a flexibilidade, economia, durabilidade e sem a dependência de um fornecedor (isso, você não precisa entrar em contato com um fornecedor para relatar ou sugerir algo).&lt;/p&gt;

&lt;p&gt;Eric Raymond era um dos membros do grupo de trabalho de Christine, publicou em 1997 algumas das ideias apresentadas em seu ensaio &lt;a href="http://www.unterstein.net/su/docs/CathBaz.pdf" rel="noopener noreferrer"&gt;"The Cathedral and the Bazaar"&lt;/a&gt;, trazendo olhos para a Netscape Communications Corporation que abriu o projeto Mozilla e liberou seu código-fonte como software livre (tenho certeza que você também já ouviu falar desse nome). No formato de open source esse código se tornou posteriormente a base do Mozilla Firefox e Thunderbird.&lt;/p&gt;

&lt;p&gt;Por conta de todo o apoio recebido ao software open source, a comunidade necessitou pensar em uma maneira de enfatizar os aspectos corporativos práticos do movimento de software livre, estabelecendo uma separação entre os termos "Open Source" e "Software Livre", na qual open source representa aspectos metodológicos, corporativos e de produção do software livre, enquanto software livre continua como representação de aspectos filosóficos sobre a liberdade de uso de software quanto ao usuário.&lt;/p&gt;

&lt;p&gt;Em 1998 é fundada a &lt;a href="https://opensource.org/osd/" rel="noopener noreferrer"&gt;Open Source Initiative&lt;/a&gt;, formalizando e estabelecendo uma definição comum em todo o setor, embora diversas empresas ainda desconfiassem do movimento open source no final dos anos 1990 e começo dos anos 2000, sendo um modelo adotado gradualmente na produção de softwares.&lt;/p&gt;

&lt;h3&gt;
  
  
  Valores
&lt;/h3&gt;

&lt;p&gt;Os principais valores para o uso de um software open source ao invés do software proprietário pode ser definido em alguns tópicos, nos quais podemos citar de acordo com a RedHat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Revisão por colaboradores&lt;/strong&gt;: o código open source é sempre verificado e aprimorado por outros programadores, já que ele fica acessível a todos e a comunidade open source é muito ativa. Imagine que o código esteja sempre em transformação, em vez de ficar fechado e estagnado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transparência&lt;/strong&gt;: você precisa saber exatamente que tipos de dados estão sendo transferidos e para qual lugar? Quer ver que mudanças foram feitas no código? Com o open source, é possível verificar e rastrear essas informações por conta própria, sem depender de fornecedores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confiabilidade&lt;/strong&gt;: para um código proprietário receber patches e estar sempre atualizado e funcionando, ele depende do autor ou da empresa que o controlam. O código open source fica livre dos autores originais, porque é sempre atualizado por meio de comunidades ativas. Já os padrões abertos e a revisão por pares garantem que o código open source seja testado corretamente e com frequência.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibilidade&lt;/strong&gt;: como o código open source tem a modificação como foco, é possível usá-lo para solucionar problemas específicos da sua empresa ou da comunidade. Você pode usar o código da maneira que quiser, além de contar com a ajuda da comunidade e com a revisão por outros desenvolvedores quando implementar novas soluções&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custo reduzido&lt;/strong&gt;: com o open source, o código em si é gratuito: ao trabalhar com empresas como a Red Hat, você paga apenas pelo suporte, fortalecimento da segurança e ajuda para gerenciar a interoperabilidade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sem dependência de fornecedor&lt;/strong&gt;: o usuário pode utilizar o código open source em qualquer lugar, finalidade e horário.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colaboração aberta&lt;/strong&gt;: com as comunidades open source ativas, você encontra ajuda, recursos e perspectivas que vão além de um grupo de interesse ou empresa.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para ver mais detalhes sobre estas definições do que chamamos de Open Source recomendo o artigo &lt;a href="https://www.redhat.com/pt-br/topics/open-source/what-is-open-source" rel="noopener noreferrer"&gt;"O que é open source?"&lt;/a&gt; publicado pela RedHat em 2019.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definições
&lt;/h2&gt;

&lt;p&gt;Certo, agora que você já viu alguns termos e conheceu toda a história por trás de todo esse movimento, acredito que já seja hora de vermos algumas definições para que tudo possa ficar ainda mais claro.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Proprietário
&lt;/h3&gt;

&lt;p&gt;Todo e qualquer software que não respeite as quatro liberdades de um software livre, não tenha código-fonte aberto, seja redistribuiído de maneira proprietária (pertence a algo ou alguém). São softwares que muitas das vezes precisam de alguma licença paga para utilização ou assinatura. Existem sim softwares proprietários gratuitos, por isso, a liberdade não vem do valor pago mas da etimologia empregada em um determinado software. Alguns exemplos de softwares proprietários:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Microsoft Windows&lt;/li&gt;
&lt;li&gt;Microsoft Office&lt;/li&gt;
&lt;li&gt;Adobe Photoshop&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Software Livre e Open Source
&lt;/h3&gt;

&lt;p&gt;A definição que realmente estrita os lados para que um software não seja mais considerado livre está muito mais relacionado com as decisões das organizações em si, tendo em vista que ambos os termos estão intrinsicamente ligados.&lt;/p&gt;

&lt;p&gt;Software Livre é todo aquele em que a licença garanta as quatro liberdades de um software livre, consequentemente, ter código-fonte aberto é basicamente um pré-requisito para ser livre. Alguns exemplos de softwares livres:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/torvalds/linux" rel="noopener noreferrer"&gt;Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/LibreOffice" rel="noopener noreferrer"&gt;LibreOffice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/GNOME/gimp" rel="noopener noreferrer"&gt;GIMP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/blender/blender" rel="noopener noreferrer"&gt;Blender&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/forem/forem" rel="noopener noreferrer"&gt;Forem&lt;/a&gt; (isso mesmo, aqui no DEV)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/scylladb" rel="noopener noreferrer"&gt;ScyllaDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tensorflow/tensorflow" rel="noopener noreferrer"&gt;TensorFlow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/docker/compose" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Certo, mas, o que garante um software ser livre no sentido de não poderem roubar ou algo do tipo? Bem, as licenças.&lt;/p&gt;

&lt;h3&gt;
  
  
  Licenças
&lt;/h3&gt;

&lt;p&gt;Por meio das licenças garantimos a integridade de um software, permitindo que ele possa continuar sendo um sofware livre e open source por meio de uma série de diretrizes.&lt;/p&gt;

&lt;p&gt;Existem diversos tipos de licenças para diversas aplicações, das quais não entrarei no mérito de explicar sobre cada uma detalhadamente, mas, acredito que o diagrama abaixo pode auxiliar nesse passo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Flanjoni%2Flpi4noobs%2Fblob%2Fmain%2Fcontent%2Fimg%2Flicencas.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Flanjoni%2Flpi4noobs%2Fblob%2Fmain%2Fcontent%2Fimg%2Flicencas.png%3Fraw%3Dtrue" alt="Licenças Open Source"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um software é considerado livre desde que respeite as quatro liberdades, mas, não necessariamente precise estar utilizando a licença GNU GPL.&lt;/p&gt;

&lt;p&gt;Para ler mais sobre licenças recomendo minha publicação no GitHub que é parte de um projeto para conteúdo educacional preparatório para a certificação LPI LE-1 (da Linux Professional Institute). Para acessar o conteúdo basta clicar &lt;a href="https://github.com/lanjoni/lpi4noobs/blob/main/content/intro/licencas.md" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalização
&lt;/h2&gt;

&lt;p&gt;Se você chegou até aqui saiba que estou muito feliz com seu novo aprendizado. Espero que todo esse conteúdo possa ter esclarecido suas dúvidas com relação ao uso de sofwares sendo Open Source ou Software Livre.&lt;/p&gt;

&lt;p&gt;Caso queira se aprofundar um pouco mais e conhecer melhor o mundo do software livre e mundo do Linux, saiba que existe um guia completo para preparação da certificação LPI Essentials (LPI LE-1), contendo todo o conteúdo introdutório que você precisa para começar a se aprofundar no uso de sistemas operacionais Linux! O melhor de tudo: o conteúdo é livre! Para acessar basta clicar &lt;a href="https://github.com/lanjoni/lpi4noobs/tree/main" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Agradeço as ponderações que o Aurélio A. Heckert (&lt;a class="mentioned-user" href="https://dev.to/aurium"&gt;@aurium&lt;/a&gt;) fez nos comentários deste artigo, exemplificando melhor alguns casos e ainda explicando de maneira mais clara alguns detalhes sobre definições citadas anteriormente, na qual realizei uma correção.&lt;/p&gt;

&lt;p&gt;Desde já agradeço você! Vamos crescer ainda mais o mundo de projetos Open Source e projetos de Software Livre!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>community</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Be Lazy and Increase Your Productivity: A Shell Discussion</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Fri, 30 Jun 2023 15:21:48 +0000</pubDate>
      <link>https://dev.to/guto/be-lazy-and-increase-your-productivity-a-shell-discussion-4obb</link>
      <guid>https://dev.to/guto/be-lazy-and-increase-your-productivity-a-shell-discussion-4obb</guid>
      <description>&lt;p&gt;Have you ever stopped to think on how many occasions you've faced the following question: how could I improve my "productivity" as a developer? Here, the objective will be to highlight some points that you can take with you for a better lifestyle and reuse of your time, even if the word &lt;em&gt;productivity&lt;/em&gt; is not yet a "correct" term (the term I seek to express). The title of this article may be a little curious, but I'm already advancing that it's not meant to be taken &lt;em&gt;literally&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
This is a simple opinion article (even the first one) that I am publishing, so please know that nothing said here is something like "a definitive truth" or something like that, after all, I will only be raising points and questions for you, Dear reader. Know that any healthy discussion is more than welcome here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Daily
&lt;/h2&gt;

&lt;p&gt;Every day each person has at least one goal to accomplish, whatever it may be, which starts at the time of awakening and "should" be accomplished by nightfall. These goals are not necessarily work tasks or anything like that... They are just discreet wishes that each of us has, goals to achieve in a short period of time (or not). At the end of the day, it's these small goals that make us move every day.&lt;/p&gt;

&lt;p&gt;The title that probably caught your eye refers to the concept of laziness.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.dictionary.com/browse/laziness"&gt;Laziness&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Noun&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;having or showing an unwillingness to work.
&lt;em&gt;"Many people start the course with a bang, but trail off after a while because of laziness, insufficient curiosity, or lack of motivation."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;the fact or quality of encouraging idleness.
&lt;em&gt;"We relaxed in the laziness of the warm afternoon, watching as the sun began to set."&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The concept of laziness is seen as a way of expressing someone who, in the inserted context, would have &lt;em&gt;aversion to meeting their goals&lt;/em&gt;, however, the concept I want to bring is someone who would have &lt;em&gt;aversion to meeting repetitive goals&lt;/em&gt; ( yes, generally). When we talk about someone who doesn't like to repeat the same things over and over again, doesn't like to live in the same flow of tasks or prefers not to repeat a certain action more than once, we are talking about the type of person I want to bring to the our context.&lt;/p&gt;

&lt;p&gt;Right, but how would a person like this imply the development of productivity? Simple: people who don't like to do the same thing twice would rather "get &lt;em&gt;someone&lt;/em&gt; to do it for them". The specific point is that this "someone" I just mentioned would be none other than our computer friends. Lazy developers prefer to automate processes instead of always repeating the same things, therefore, the energy spent is no longer to carry out the same activity every day, but to find a solution that can meet this need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatic pilot
&lt;/h2&gt;

&lt;p&gt;Now that you understand what kind of people this article is aimed at, I hope your doubts have been clarified (so far). Maybe it's time for you to turn on autopilot and look around at the amount of tools you can use to improve your development process.&lt;/p&gt;

&lt;p&gt;The point in question is: with the advancement of technology and the increase in the ease of access of the population, the creation of new technologies that seek to help in people's daily lives is immense. Look around at the number of devices that make you stay connected to the Internet, whether directly or indirectly, having an impact on your life. There are many of these devices, but you as a developer may not use or even realize the powerful tools you have in your hands for consistent energy expenditure.&lt;/p&gt;

&lt;p&gt;When I talk about tools, I'm not talking about huge platforms or highly end-user oriented tools that will make direct use of that software... I'm not even talking about other software that you should probably use to organize your schedule (they are important and necessary, but, I want to go deeper)... I'm talking about tools that for years were the beginnings of what we know as computers, which were known as the only ways to use them. Yes, I'm talking nothing less than your terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminal
&lt;/h2&gt;

&lt;p&gt;Going back to what boiled down to the main human-computer interaction interface that existed a few decades ago, we know that terminals became popular and are still used today (or at least they should be).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KOQ67VAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://upload.wikimedia.org/wikipedia/commons/thumb/6/69/IBM_PC_5150.jpg/280px-IBM_PC_5150.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KOQ67VAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://upload.wikimedia.org/wikipedia/commons/thumb/6/69/IBM_PC_5150.jpg/280px-IBM_PC_5150.jpg" alt="1981 IBM 5150 PC" width="280" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The image above depicts a 1981 IBM 5150 PC.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Currently, terminal emulators seek to simulate the interactions that occurred in times when a "black screen with green letters" was the only visual interface style presentable by monitors. Obviously terminal emulators are very user friendly, allowing different customizations and expanding the imagination of those who will use them (if you are interested in learning some ways to customize your terminal emulator click &lt;a href="https://dev.to/guto/taking-the-terminal-to-the-next-level-customizing-features-3eck"&gt;here&lt;/a&gt; and access one of my past articles).&lt;/p&gt;

&lt;p&gt;The point I want to highlight here is: these have always been the main interfaces to be used when working with computers (in general terms). Its interface is based on an input of commands that are processed and an explicit output resulting from the processing of these commands. There is usually a bit of a misunderstanding on the part of general users to think "okay, but if technology has evolved so much, why should I continue using something like this" or "it's a waste of time to use something outdated", but I already anticipate that they are misled into thinking that way.&lt;/p&gt;

&lt;p&gt;The main argument that favors the use of terminal emulators is simplicity. There is no middle ground, access area lock, rendering time or bad animation (whatever is a common problem of a general purpose GUI). The commands are executed, you control the computer as you wish and manage the main activities of your daily life.&lt;/p&gt;

&lt;p&gt;There are several solutions that seek to bring real experiences similar to the use of interfaces in terminal emulators, it is not difficult to find some software that makes its appearance elegant, being able to navigate with arrows or something like that. The point at hand is: obviously the use of a graphical interface aimed at an end user is more "pleasant", after all, it was created to be used by a general user.&lt;/p&gt;

&lt;p&gt;Okay, so does that mean that for me to increase my "productivity" I have to use a terminal emulator? No! I'm saying that exploring the use of some tools through the terminal emulator can be a new and enjoyable experience, which in the future &lt;strong&gt;will&lt;/strong&gt; turn out to be of its own benefit (after all, you managed to learn something new and put the mouse aside for a bit , and could even be a benefit to your health, right?).&lt;/p&gt;

&lt;h2&gt;
  
  
  Scripts
&lt;/h2&gt;

&lt;p&gt;Ok, the use of a terminal emulator may not be to everyone's liking, I confess, but know that mixing its use with other tools can be a powerful combination, one of which is the use of scripts! Yes, scripts in the sense of instruction orders!&lt;/p&gt;

&lt;p&gt;Terminal emulators work on a high level of abstraction layer so that the user can execute commands to be interpreted by a shell interpreter and sent to the kernel, performing communication with the hardware. The process itself is done literally with layers of abstraction. Every command you run is checked, interpreted, and executed according to the constraints previously set in your interpreter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I_jKdH1P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--KqSJ0S9y--/c_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_800/https://i.stack.imgur.com/Znlqz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I_jKdH1P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--KqSJ0S9y--/c_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_800/https://i.stack.imgur.com/Znlqz.jpg" alt="Abstraction layers in the kernel" width="240" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The image above shows how a user's input (executed command) is made, being sent to the shell interpreter and subsequently executed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you use any system that is based or inspired by UNIX (such as Linux distributions, macOS, FreeBSD, OpenBSD and BSD's in general) know that you have a powerful tool to use: scripts for your shell interpreter.&lt;/p&gt;

&lt;p&gt;The famous &lt;em&gt;shell scripts&lt;/em&gt; that have as main interpreters (better known) &lt;a href="https://www.gnu.org/software/bash/"&gt;GNU Bash&lt;/a&gt;, &lt;a href="https://www.zsh.org/"&gt;Zsh&lt;/a&gt;, &lt;a href="https://fishshell.com/"&gt;Fish&lt;/a&gt;, &lt;a href="https://www.tcsh.org/"&gt;TCSH&lt;/a&gt; among many others, have ways of executing commands (working as a programming language) directly, enabling the creation of automation routines, shortening configuration processes, among other different ways so that you can increasingly automate your development routine.&lt;/p&gt;

&lt;p&gt;The scripts can be created in different ways, used for infinite possibilities, opening up a huge range for your learning. At this point, I will leave my mentions to the main people responsible for producing excellent quality content on the use of shell scripts and the Linux world in general:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blauaraujo.com/"&gt;Blau Araujo (@blau_araujo)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://diolinux.com.br/"&gt;Dionatan (@blogdiolinux)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linuxtips.io/"&gt;Jeferson Fernando (@badtux_)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://slackjeff.com.br/"&gt;Jefferson Carneiro (@oslackjeff)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;These guys are &lt;strong&gt;amazing&lt;/strong&gt; when it comes to the Linux world.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course, if you want to learn a little more about Linux and still prepare for a Linux Professional Institute certification, know that there is an &lt;strong&gt;excellent&lt;/strong&gt; guide that will help you along the way, the famous &lt;a href="https://github.com/lanjoni/lpi4noobs"&gt;lpi4noobs&lt;/a&gt; written with a lot of love and affection by the one who is writing the article you just read!&lt;/p&gt;

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

&lt;p&gt;Learning to better utilize the tools you have around you is the best thing. Be curious, seek to learn about the use of different technologies. At the end of the day, nobody likes to perform a repetitive task on a daily basis as a developer, so maybe it's time to explore new paths and understand that this whole learning process is part of it.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed the article, I wrote it as a way to express a little more about a perspective resulting from the observation of published content related to the term "productivity", which I still consider to be a &lt;em&gt;wrong&lt;/em&gt; term. Finally, the intention was to leave a little of the technical content itself and take a look at the environment in which we are inserted.&lt;/p&gt;

&lt;p&gt;Be happy, thanks for reading this far.&lt;/p&gt;

</description>
      <category>shell</category>
      <category>linux</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Seja preguiçoso e aumente sua produtividade: uma discussão sobre Shell</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Fri, 30 Jun 2023 15:17:58 +0000</pubDate>
      <link>https://dev.to/guto/seja-preguicoso-e-aumente-sua-produtividade-uma-discussao-sobre-shell-2ned</link>
      <guid>https://dev.to/guto/seja-preguicoso-e-aumente-sua-produtividade-uma-discussao-sobre-shell-2ned</guid>
      <description>&lt;p&gt;Já parou pra pensar em quantas ocasiões você se deparou com a seguinte questão: como eu poderia melhorar a minha "produtividade" como desenvolvedor? Aqui, o objetivo vai ser ressaltar alguns pontos que você pode levar consigo para um melhor estilo de vida e reaproveitamento de seu tempo, mesmo que a palavra &lt;em&gt;produtividade&lt;/em&gt; ainda não seja um termo "correto" (o termo que busco expressar). O título deste artigo pode ser um tanto quanto curioso, mas, já adianto que não é pra levar &lt;em&gt;ao pé da letra&lt;/em&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;&lt;br&gt;
Este é um simples artigo (até mesmo o primeiro) de opinião que estou publicando, por isso, saiba que nada dito aqui é algo como "uma verdade definitiva" ou algo do tipo, afinal, estarei levantando apenas pontos e questionamentos para você, caro leitor. Saiba que qualquer discussão saudável é muito mais do que bem-vinda aqui.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cotidiano
&lt;/h2&gt;

&lt;p&gt;Todos os dias cada pessoa possui pelo menos uma meta para realizar, qualquer que seja, que inicia no momento do despertar e "deveria" ser cumprida até o anoitecer. Estas metas não são necessariamente tarefas do trabalho ou algo do tipo... São apenas vontades discretas que cada um de nós possui, objetivos para alcançarmos em um curto período de tempo (ou não). No final das contas, são essas pequenas metas que fazem com que a gente se movimente todos os dias.&lt;/p&gt;

&lt;p&gt;O título que provavelmente pode ter chamado sua atenção se refere ao conceito de preguiça.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.google.com.br/search?&amp;amp;q=pregui%C3%A7a"&gt;Preguiça&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Substantivo feminino&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;aversão ao trabalho; ócio, vadiagem.
&lt;em&gt;"o pai não permite que os filhos vivam na p."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;estado de prostração e moleza, de causa orgânica ou psíquica.
&lt;em&gt;"tem p. de caminhar"&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O conceito de preguiça é visto como uma forma de expressar alguém que, no contexto inserido, teria &lt;em&gt;aversão ao cumprimento de suas metas&lt;/em&gt;, porém, o conceito que estou querendo trazer é de alguém que teria &lt;em&gt;aversão ao cumprimento de metas repetitivas&lt;/em&gt; (sim, em âmbito geral). Quando falamos de alguém que não gosta de repetir sempre as mesmas coisas, não gosta de viver sempre em um mesmo fluxo de tarefas ou então prefere por não repetir mais de uma vez determinada ação, estamos falando do tipo de pessoa que estou querendo trazer para o nosso contexto.&lt;/p&gt;

&lt;p&gt;Certo, mas, como uma pessoa desta forma implicaria no desenvolvimento de produtividade? Simples: pessoas que não gostam de fazer a mesma coisa duas vezes preferem "dar um jeito para &lt;em&gt;alguém&lt;/em&gt; fazer para elas". O ponto específico é que este "alguém" que eu acabei de citar, seria nada mais nada menos que nossos amigos computadores. Desenvolvedores preguiçosos preferem automatizar processos ao invés de sempre repetirem as mesmas coisas, por isso, o gasto de energia empregado não é mais para realizar a mesma atividade todos os dias, mas, para encontrar uma solução que consiga suprir esta necessidade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Piloto automático
&lt;/h2&gt;

&lt;p&gt;Agora que você já entendeu pra qual tipo de pessoas este artigo é direcionado, espero que as suas dúvidas tenham sido esclarecidas (até o momento). Talvez seja hora de você ligar o piloto automático e olhar ao seu redor vendo a quantidade de ferramentas que você pode utilizar para melhorar seu processo de desenvolvimento. &lt;/p&gt;

&lt;p&gt;O ponto em questão é: com o avanço da tecnologia e o aumento da facilidade de acesso da população, a criação de novas tecnologias que buscam auxiliar no cotidiano das pessoas é imensa. Veja em volta o número de equipamentos que te fazem permanecer conectado na Internet, seja de forma direta ou indireta, tendo um reflexo em sua vida. Existem diversos destes equipamentos, mas, você como desenvolvedor pode não fazer uso ou nem ao menos perceber as poderosas ferramentas que tem em suas mãos para um gasto de energia coerente.&lt;/p&gt;

&lt;p&gt;Quando eu falo de ferramentas, não estou falando de plataformas enormes ou ferramentas altamente voltadas para um usuário final que vai fazer uso direto daquele software... Não estou falando nem mesmo de outros softwares que você provavelmente deve utilizar para organizar seu cronograma (eles são importantes e necessários, mas, eu quero ir mais embaixo)... Estou falando de ferramentas que por anos eram os primórdios do que conhecemos como computadores, das quais eram conhecidas como as únicas formas de utilizarmos. Sim, estou falando nada mais nada menos do que seu terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminal
&lt;/h2&gt;

&lt;p&gt;Voltando ao que se resumia na principal interface de interação humano-computador que existia há algumas décadas, sabemos que os terminais se popularizaram e são utilizados até hoje (ou pelo menos deveriam).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KOQ67VAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://upload.wikimedia.org/wikipedia/commons/thumb/6/69/IBM_PC_5150.jpg/280px-IBM_PC_5150.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KOQ67VAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://upload.wikimedia.org/wikipedia/commons/thumb/6/69/IBM_PC_5150.jpg/280px-IBM_PC_5150.jpg" alt="IBM 5150 PC de 1981" width="280" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A imagem acima retrata um IBM 5150 PC de 1981.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Atualmente os emuladores de terminal buscam simular as interações que ocorriam nas épocas em que uma "tela preta com letras verdes" era o único estilo de interface visual apresentável por monitores. Obviamente os emuladores de terminal são muito amigáveis, permitindo customizações diversas e expandindo a imaginação daqueles que vão utilizá-los (se você tem interesse em aprender algumas formas de customizar seu emulador de terminal clique &lt;a href="https://dev.to/guto/elevando-o-nivel-do-terminal-customizando-suas-funcionalidades-2amm"&gt;aqui&lt;/a&gt; e acesse um dos meus artigos passados).&lt;/p&gt;

&lt;p&gt;O ponto que quero destacar aqui é: estas sempre foram as principais interfaces a serem utilizadas quando trabalhávamos com computadores (no aspecto geral). Sua interface se baseia em uma entrada de comandos que são processados e uma saída explícita resultante do processamento destes comandos. Geralmente existe um tanto quanto equívoco dos usuários gerais em pensar "ok, mas, se a tecnologia evoluiu tanto por qual motivo eu deveria continuar utilizando algo deste tipo" ou então "é perca de tempo utilizar algo ultrapassado", mas, já adianto que estão enganados em pensar dessa forma.&lt;/p&gt;

&lt;p&gt;O principal argumento que favorece o uso de emuladores de terminal é a simplicidade. Não existe meio termo, trava de área de acesso, tempo de renderização ou animação com problema (qualquer que seja um problema comum de uma interface gráfica de propósito geral). Os comandos são executados, você controla o computador como você bem quiser e consegue ainda gerenciar as principais atividades do seu cotidiano.&lt;/p&gt;

&lt;p&gt;Existem diversas soluções que buscam trazer experiências reais similares ao uso de interfaces em emuladores de terminal, não é difícil de se encontrar algum software que faça com que sua aparência seja elegante, podendo navegar com setas ou algo do tipo. O ponto em questão é: obviamente o uso de uma interface gráfica voltada para um usuário final é mais "agradável", afinal, ela foi criada para ser utilizada por um usuário de âmbito geral.&lt;/p&gt;

&lt;p&gt;Certo, então quer dizer que pra eu aumentar minha "produtividade" eu tenho que usar um emulador de terminal? Não! Estou dizendo que explorar o uso de algumas ferramentas pelo emulador de terminal pode ser uma experiência nova e agradável, que no futuro &lt;strong&gt;vai&lt;/strong&gt; resultar em um benefício próprio (afinal, você conseguiu aprender algo novo e deixar de lado o mouse um pouco, podendo até mesmo ser um benefício para sua saúde, não é?).&lt;/p&gt;

&lt;h2&gt;
  
  
  Scripts
&lt;/h2&gt;

&lt;p&gt;Ok, o uso de um emulador de terminal pode não ser do agrado de todos, eu confesso, mas, saiba que mesclar o uso dele com outras ferramentas pode ser uma combinação poderosa, sendo uma delas o uso de scripts! Sim, scripts no sentido de ordens de instrução mesmo!&lt;/p&gt;

&lt;p&gt;Os emuladores de terminal trabalham em uma camada de alto nível de abstração para que o usuário possa executar comandos a serem interpretados por um interpretador de shell e enviados para o kernel, realizando a comunicação com o hardware. O processo em si é feito literalmente com camadas de abstração. Todo comando que você executa é verificado, interpretado e executado de acordo com as restrições previamente estabelecidas no seu interpretador.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I_jKdH1P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--KqSJ0S9y--/c_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_800/https://i.stack.imgur.com/Znlqz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I_jKdH1P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--KqSJ0S9y--/c_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_800/https://i.stack.imgur.com/Znlqz.jpg" alt="Camadas de abstração no kernel" width="240" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A imagem acima mostra como a entrada de um usuário (comando executado) é feita, sendo enviada para o interpretador de shell e posteriormente executada.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Se você utiliza qualquer sistema que seja baseado ou inspirado no UNIX (como distribuições Linux, macOS, FreeBSD, OpenBSD e BSD's no geral) saiba que você tem consigo uma ferramenta poderosa a ser utilizada: scripts para seu interpretador de shell. &lt;/p&gt;

&lt;p&gt;Os famosos &lt;em&gt;shell scripts&lt;/em&gt; que possuem como interpretadores principais (mais conhecidos) &lt;a href="https://www.gnu.org/software/bash/"&gt;GNU Bash&lt;/a&gt;, &lt;a href="https://www.zsh.org/"&gt;Zsh&lt;/a&gt;, &lt;a href="https://fishshell.com/"&gt;Fish&lt;/a&gt;, &lt;a href="https://www.tcsh.org/"&gt;TCSH&lt;/a&gt; entre outros diversos, possuem formas de executar comandos (funcionando como uma linguagem de programação) diretamente, possibilitando a criação de rotinas de automação, encurtamento de processos de configuração, entre outras diversas formas para que você possa cada vez mais automatizar sua rotina de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Os scripts podem ser criados de diversas maneiras, utilizados para infinitas possibilidades, abrindo um leque enorme para seu aprendizado. Neste momento vou deixar minhas menções para os principais responsáveis por produzirem conteúdos de excelentíssima qualidade sobre uso de scripts em shell e o mundo Linux de forma geral:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blauaraujo.com/"&gt;Blau Araujo (@blau_araujo)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://diolinux.com.br/"&gt;Dionatan (@blogdiolinux)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linuxtips.io/"&gt;Jeferson Fernando (@badtux_)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://slackjeff.com.br/"&gt;Jefferson Carneiro (@oslackjeff)&lt;/a&gt;
&amp;gt; Estes caras são &lt;strong&gt;feras&lt;/strong&gt; quando o assunto é mundo Linux.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claro, se você quiser aprender um pouco mais sobre Linux e ainda se preparar para uma certificação da Linux Professional Institute, saiba que existe um guia &lt;strong&gt;excelente&lt;/strong&gt; que vai te ajudar nesse caminho, o famoso &lt;a href="https://github.com/lanjoni/lpi4noobs"&gt;lpi4noobs&lt;/a&gt; escrito com muito amor e carinho por este que está escrevendo o artigo que você acabou de ler!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Aprender a utilizar melhor as ferramentas que você tem ao seu redor é a melhor coisa. Seja curioso, busque aprender sobre o uso de tecnologias diversas. No final das contas, ninguém gosta de realizar uma tarefa repetitiva no cotidiano como desenvolvedor, por isso, talvez seja hora de explorar novos caminhos e entender que faz parte todo esse processo de aprendizado.&lt;/p&gt;

&lt;p&gt;Espero que tenham gostado do artigo, escrevi como uma forma de expressar um pouco mais sobre uma perspectiva resultante da observação de conteúdos publicados relacionados ao termo "produtividade", que ainda assim considero como um termo &lt;em&gt;errado&lt;/em&gt;. Por fim, o intuito foi sair um pouco do conteúdo técnico em si e dar uma olhada para o ambiente que estamos inseridos.&lt;/p&gt;

&lt;p&gt;Sejam felizes, obrigado por lerem até aqui.&lt;/p&gt;

</description>
      <category>shell</category>
      <category>linux</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Primeiros passos com o Git</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Mon, 19 Jun 2023 01:40:29 +0000</pubDate>
      <link>https://dev.to/guto/primeiros-passos-com-o-git-8l1</link>
      <guid>https://dev.to/guto/primeiros-passos-com-o-git-8l1</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; O que é Git?

&lt;ul&gt;
&lt;li&gt; De onde surgiu o Git?
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt; Conceitos por trás do Git

&lt;ul&gt;
&lt;li&gt; Repositório
&lt;/li&gt;
&lt;li&gt; Commit
&lt;/li&gt;
&lt;li&gt; Branch
&lt;/li&gt;
&lt;li&gt; Pull Request
&lt;/li&gt;
&lt;li&gt; Issue (bônus)
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt; Comandos
&lt;/li&gt;
&lt;li&gt; Extra

&lt;ul&gt;
&lt;li&gt; Git x GitHub
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="orgb058b04"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Git?
&lt;/h2&gt;

&lt;p&gt;Git é uma ferramenta/protocolo para controle de versões de um projeto (repositório). A principal finalidade do Git é controlar o fluxo de modificações que um projeto pode receber.&lt;/p&gt;

&lt;p&gt;Além disso, o Git auxilia no decorrer do processo de desenvolvimento por conseguir facilitar o registro de modificações que um repositório pode sofrer.&lt;/p&gt;

&lt;p&gt;&lt;a id="org3524200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  De onde surgiu o Git?
&lt;/h3&gt;

&lt;p&gt;Desenvolvido por nada mais nada menos que Linus Torvalds (juntamente de diversos desenvolvedores espalhados no mundo todo - poder do software livre e de código aberto neh), o Git surgiu com o principal propósito de organizar repositórios, buscando ser uma solução livre e de fácil uso.&lt;/p&gt;

&lt;p&gt;O principal motivo que realmente fez com que o Git surgisse foi a manutenção do repositório do Kernel Linux. Depois de tentar utilizar diversas ferramentas para o versionamento, mas, nenhuma suprindo consideravelmente bem… Com isso, Linus propôs em 2004 o desenvolvimento de uma nova ferramenta, assim, surgiu-se o Git.&lt;/p&gt;

&lt;p&gt;&lt;a id="orgc6320b8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conceitos por trás do Git
&lt;/h2&gt;

&lt;p&gt;&lt;a id="org5cd400b"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Repositório
&lt;/h3&gt;

&lt;p&gt;Local onde temos o nosso projeto. Nele teremos todo o controle de versões e modificações realizadas. No repositório podemos navegar entre os arquivos normalmente e verificar históricos essenciais.&lt;/p&gt;

&lt;p&gt;Um repositório pode ser nomeado com um padrão bem interessante em sistemas que utilizam o git (como GitHub e GitLab), sendo &lt;em&gt;usuário/repositório&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Os repositórios podem sofrer diversas modificações, por isso, vamos entender melhor como essas modificações são realizadas.&lt;/p&gt;

&lt;p&gt;&lt;a id="org70b48c7"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Commit
&lt;/h3&gt;

&lt;p&gt;Um commit pode ser classificado como uma publicação de modificação no repositório. Se eu altero algo de um repositório, temos o registro salvo com nome de commit, sendo apresentado quais modificações foram realizadas (desde criação de arquivos até modificações únicas de caracteres).&lt;/p&gt;

&lt;p&gt;Com o git podemos registrar todos os commits feitos, apresentando também informações como data, mensagem, usuário que enviou o commit entre outros dados realcionados ao commit!&lt;/p&gt;

&lt;p&gt;&lt;a id="org754caf0"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Branch
&lt;/h3&gt;

&lt;p&gt;Podemos definir a branch como uma ramificação do nosso repositório. Nela, temos a base de outra branch (geralmente a main - antiga master) para realizar modificações.&lt;/p&gt;

&lt;p&gt;Em projetos reais, é comum que cada modificação de projeto (algo que altere o fluxo de funcionamento) tenha uma branch específica. Cada modificação posteriormente pode resultar em uma mescla dessa branch com a principal (realizando o &lt;em&gt;merge&lt;/em&gt; das modificações).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9tt8OctJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.nobledesktop.com/image/gitresources/git-branches-merge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9tt8OctJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.nobledesktop.com/image/gitresources/git-branches-merge.png" alt="Demonstração de branch" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="org5c827b3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pull Request
&lt;/h3&gt;

&lt;p&gt;Nada mais é do que uma requisição para se realizar o merge (fundir) de uma branch em outra. Geralmente as pull requests são abertas para realizar o merge de uma branch modificada para a branch principal, resultando em um processo de aprovação.&lt;/p&gt;

&lt;p&gt;Com a pull request aberta temos acesso às modificações que serão "mergeadas" ao se aprovar o pedido. Tome muito cuidado! As pull requests devem ser utilizadas com cautela e sempre que possível, impossibilitando modificações problemáticas.&lt;/p&gt;

&lt;p&gt;&lt;a id="org702b4f4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue (bônus)
&lt;/h3&gt;

&lt;p&gt;Geralmente sendo uma característica única de sistemas que utilizam o versionamento com git, uma issue pode ser definida como algum problema/sugestão para modificação no repositório. As issues são abertas e recebem comentários, podendo ser fechadas pelo(s) proprietário(s) do repositório.&lt;/p&gt;

&lt;p&gt;São extremamente úteis para realizar uma verificação geral de uso, podendo ainda ser uma fonte de &lt;em&gt;feedback&lt;/em&gt; para o repositório.&lt;/p&gt;

&lt;p&gt;&lt;a id="org3497fbe"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comandos
&lt;/h2&gt;

&lt;p&gt;Existem diversos comandos para se utilizar com o git, por isso, recomendo acessar a documentação de &lt;a href="https://git-scm.com/docs"&gt;apresentação dos comandos&lt;/a&gt; caso queira se aprofundar melhor!&lt;/p&gt;

&lt;p&gt;Vamos ver alguns comandos específicos do git:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;git config&lt;/strong&gt;: utilizado para configurar seu usuário&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git init&lt;/strong&gt;: inicia um repositório no diretório local&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git clone&lt;/strong&gt;: clona um repositório existente no caminho atual&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git pull&lt;/strong&gt;: sincroniza as modificações existentes que não estão atualizadas para o seu repositório&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git add&lt;/strong&gt;: adiciona arquivos para serem sincronizados e enviados&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git commit&lt;/strong&gt;: adiciona um commit com os arquivos que foram previamente modificados&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git push&lt;/strong&gt;: envia as modificações do seu repositório local para o repositório principal&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git checkout&lt;/strong&gt;: atualizar a branch que você está utilizando no momento&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git merge&lt;/strong&gt;: utilizado para fundir uma branch com outra, geralmente em paralelo com uma pull request&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git log&lt;/strong&gt;: mostra os logs de commits realizados&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;git revert&lt;/strong&gt;: reverter commits realizados para uma versão anterior às modificações&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="orgecac49b"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra
&lt;/h2&gt;

&lt;p&gt;&lt;a id="org5b2e314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Git x GitHub
&lt;/h3&gt;

&lt;p&gt;Git &lt;strong&gt;NÃO&lt;/strong&gt; é a mesma coisa que GitHub. Enquanto o Git é tratado como uma ferramenta, o GitHub é utilizado como um site/plataforma que realiza o uso do Git para sistema de versionamento.&lt;/p&gt;

&lt;p&gt;O Git pode ser implementado em um servidor como desejar, independente da plataforma a ser utilizada no final. Existem diversas plataformas que utilizam o Git, entre elas o GitLab, por exemplo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aprenda mais sobre Git
&lt;/h3&gt;

&lt;p&gt;Acesse o repositório oficial do &lt;a href="https://github.com/DanielHe4rt/git4noobs"&gt;git4noobs&lt;/a&gt; para aprender mais sobre Git!&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Manipulating JSON files with Crystal</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Tue, 06 Jun 2023 01:43:34 +0000</pubDate>
      <link>https://dev.to/guto/manipulating-json-files-with-crystal-4gkk</link>
      <guid>https://dev.to/guto/manipulating-json-files-with-crystal-4gkk</guid>
      <description>&lt;p&gt;If you ever thought about what it would be like to work with reading JSON files using Crystal, know that this is the right place! Here we will see how we can perform simple manipulations of values in JSON, working with variables, arrays, hashs, among other ways, manipulating our keys with variables!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is JSON
&lt;/h2&gt;

&lt;p&gt;The name JSON comes from "JavaScript Object Notation", being a compact open standard format for exchanging and manipulating simple data, created in the 2000s (more specifically in 2002) using a key-value format (attribute-value).&lt;br&gt;
Okay, but what would a JSON file format look like?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"talk troop"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"response"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hey"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The keys/attributes would be the fields &lt;code&gt;"message"&lt;/code&gt; and &lt;code&gt;"response"&lt;/code&gt;, in which its value is assigned right after the colon (":"), being separated by braces ("{ }") and a comma indicating the next complete attribute.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Working with Crystal
&lt;/h2&gt;

&lt;p&gt;Opening your working directory, create a new directory to work with this project, in which we will need some "dependencies" before starting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure you have Crystal installed correctly on your machine&lt;/li&gt;
&lt;li&gt;Prepare the favorite code editor in the directory that was created&lt;/li&gt;
&lt;li&gt;If you haven't installed Crystal yet click &lt;a href="https://crystal-lang.org/install"&gt;here&lt;/a&gt; to learn more!
After opening your working directory, if you want to start &lt;code&gt;shards&lt;/code&gt; to create a file to control the project, execute in your terminal:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;shards init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your &lt;code&gt;shard.yml&lt;/code&gt; file should follow the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;json-reader&lt;/span&gt;

&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.1.0&lt;/span&gt;

&lt;span class="na"&gt;authors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;João Lanjoni &amp;lt;guto@lanjoni.dev&amp;gt;&lt;/span&gt;

&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;JSON reader&lt;/span&gt;

&lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src/main.cr&lt;/span&gt;

&lt;span class="na"&gt;license&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MIT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create a directory called &lt;code&gt;src&lt;/code&gt;, in it we will put all our code worked using Crystal! Also create a directory called &lt;code&gt;content&lt;/code&gt; in the root of the project to contain all our files in &lt;code&gt;JSON&lt;/code&gt; format!&lt;br&gt;
Therefore, just add a file in &lt;code&gt;JSON&lt;/code&gt; format with the name you want in the &lt;code&gt;content&lt;/code&gt; directory and add a &lt;code&gt;main.cr&lt;/code&gt; file in the &lt;code&gt;src&lt;/code&gt; directory, so we will have our tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;json-reader/
├── content/
│ └── index.json
├── src/
│ └── main.cr
└── shard.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Remembering that &lt;code&gt;shard.yml&lt;/code&gt; only exists if you started shards inside your project!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Hands-on (on keyboard)
&lt;/h2&gt;

&lt;p&gt;First, let's create our JSON file, so, following the template above, create a &lt;code&gt;.json&lt;/code&gt; file inside the &lt;code&gt;content&lt;/code&gt; directory! With it we will manipulate the existing values there!&lt;br&gt;
Now open your &lt;code&gt;src/main.cr&lt;/code&gt; file in your favorite code editor so we can better manipulate our project!&lt;br&gt;
Opening your file first let's import the &lt;code&gt;json&lt;/code&gt; library to work with files in this format, so add in your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Every library can be added with the &lt;code&gt;require&lt;/code&gt; command!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In order to inform which file will be read, we will perform a simple pass by argument/option when running our project! So, if you want to go a little deeper into passing arguments on the command line with Crystal, click &lt;a href="https://crystal-lang.org/api/1.8.2/toplevel.html"&gt;here&lt;/a&gt;. In this way, let's save the content of the JSON file in a variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"content/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;To receive the first argument/option we will use &lt;code&gt;ARGV[0]&lt;/code&gt;, after all, position 0 is the first in the array of values passed as options! The &lt;code&gt;content&lt;/code&gt; at the beginning means that we only need to pass the file name, after all, a file with the same name will already be searched for in the specified directory!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Right, but there is still the case of the user not adding any option, right? In this case, the code should not even continue, after all, if a JSON file is not specified, then, we cannot carry out the manipulation! So, before that, we add a simple check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"You must pass the filename as a parameter!"&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The length being different from 1 shows that either more than one argument was passed or none at all, so in both cases we must reject the execution!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are a few ways to parse our JSON, let's start with the simplest: JSON with unique keys! See the example JSON below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bye"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Notice that this format does not have square brackets at the beginning, indicating that it is not an array!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To perform the &lt;code&gt;parse&lt;/code&gt; we will use a native Crystal function to read a JSON and then convert it into a Hash of Strings!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;hash_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;hash_content&lt;/span&gt; &lt;span class="c1"&gt;# {"test" =&amp;gt; "hi", "test2" =&amp;gt; "bye"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In this way, we are going to assemble a variable named &lt;code&gt;hash_content&lt;/code&gt;, having in its content a hash with a key value from String to String, bringing this data from a JSON&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So our final code will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"json"&lt;/span&gt;

&lt;span class="c1"&gt;# Check arguments being equal to 1&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"You must pass the filename as a parameter!"&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Loading the contents of the JSON file&lt;/span&gt;
&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"content/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Transforming JSON file data into a String Hash =&amp;gt; String&lt;/span&gt;
&lt;span class="n"&gt;hash_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Printing the contents of the variable&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;hash_content&lt;/span&gt; &lt;span class="c1"&gt;# {"test" =&amp;gt; "hi", "test2" =&amp;gt; "bye"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can run it in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Using shards:
&lt;/h2&gt;

&lt;p&gt;&lt;br&gt;
&lt;code&gt;$ shards run -- content.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Using the &lt;code&gt;crystal&lt;/code&gt; itself:
&lt;/h2&gt;

&lt;p&gt;&lt;br&gt;
&lt;code&gt;$ crystal run src/main.cr content.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, but what if we just wanted the &lt;code&gt;test&lt;/code&gt; key returned?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;hash_content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# hi&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Thus, we were able to manipulate our data in the JSON file, being able to bring the specific keys for each item!&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON Arrays
&lt;/h2&gt;

&lt;p&gt;Okay, but most of the JSONs we're going to find need to be "parsed" using Array formats... How can we do that? Well, there are two specific ways to accomplish this task, let's go?&lt;/p&gt;

&lt;h3&gt;
  
  
  First form: Hash Array
&lt;/h3&gt;

&lt;p&gt;Basically let's assemble an array with its internal type being hashed! But how would that look in practice? Well, first I'll go over the JSON file we'll be working with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"test2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hey"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's first define that we are working with an array, but, when defining the array type, let's change it to &lt;code&gt;Hash(String, String)&lt;/code&gt;, see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="c1"&gt;# [{"test" =&amp;gt; "hello"}, {"test2" =&amp;gt; "hey"}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we've basically wrapped the previous hash format in the array, correct? So we can work with our arrays of JSONs the way we prefer! But, how could I bring only the contents of the "test" key? Simple, see two examples below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# {"test" =&amp;gt; "hello"}&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# hello&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we can manipulate our JSON!&lt;br&gt;
If the key format is not always String, we can still create an &lt;code&gt;alias&lt;/code&gt; to manipulate the types passed by Hash or just add a pipe operator ("|") demonstrating that the type can vary, so it would be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Second way: File.open
&lt;/h3&gt;

&lt;p&gt;We can also use &lt;code&gt;File.open&lt;/code&gt; to open a file and work with its content (in which I leave the credits to &lt;a href="https://twitter.com/cherry_ramatis"&gt;cherry&lt;/a&gt; for being on &lt;a href="//twitch.%20tv/gutolanjoni"&gt;live&lt;/a&gt; and leaving this very important detail), without the need to create a variable to carry out this work (as we were doing with the &lt;code&gt;content&lt;/code&gt; variable). See an implementation below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"content/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="c1"&gt;# [{"test" =&amp;gt; "hello"}, {"test2" =&amp;gt; "hey"}]&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# {"test" =&amp;gt; "hello"}&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# hello&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In this example we perform a simple "parse" of values and update them in the variable named &lt;code&gt;json&lt;/code&gt;, being able to work with the values in the same format as before!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thus, our complete project ends up in the second shape! Here's how our finished code looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"json"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"You must pass the filename as a parameter!"&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"content/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="c1"&gt;# [{"test" =&amp;gt; "hello"}, {"test2" =&amp;gt; "hey"}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Finalization
&lt;/h2&gt;

&lt;p&gt;With this guide and small article you learned how to manipulate JSON files and data coming from other files using Crystal, based on the key-value model that is offered, being able to create commands, specific readings, among other types of projects! To access the code developed in this article just click &lt;a href="https://github.com/lanjoni/json-reader-crystal"&gt;here&lt;/a&gt;!&lt;br&gt;
See you next time, see you later! Crystallize your day even more! 💎 🖤&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>json</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Manipulando arquivos JSON com Crystal</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Tue, 06 Jun 2023 00:53:38 +0000</pubDate>
      <link>https://dev.to/guto/manipulando-arquivos-json-com-crystal-j6d</link>
      <guid>https://dev.to/guto/manipulando-arquivos-json-com-crystal-j6d</guid>
      <description>&lt;p&gt;Se você alguma vez já pensou em como seria trabalhar com a leitura de arquivos JSON utilizando Crystal, saiba que este é o lugar certo! Aqui veremos como podemos realizar manipulações simples de valores em JSON, trabalhando com variáveis, arrays, hashs, entre outras maneiras, manipulando nossas chaves com variáveis!&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é JSON
&lt;/h2&gt;

&lt;p&gt;O nome JSON vem de "JavaScript Object Notation", sendo um formato compacto de padrão aberto para troca e manipulação de dados simples, criado ainda nos anos 2000 (mais especificamente em 2002) utilizando um formato de chave-valor (atributo-valor).&lt;br&gt;
Ok, mas, como seria o formato de um arquivo JSON?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mensagem"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fala tropa"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"resposta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eai"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;As chaves/atributos seriam os campos &lt;code&gt;"mensagem"&lt;/code&gt; e &lt;code&gt;"resposta"&lt;/code&gt;, na qual seu valor está atribuído logo após dos dois pontos (":"), sendo separadas por chaves ("{ }") e vírgula indicando o próximo atributo completo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Trabalhando com Crystal
&lt;/h2&gt;

&lt;p&gt;Abrindo seu diretório de trabalho, crie um novo diretório para trabalharmos com este projeto, na qual vamos precisar de algumas "dependências" antes de iniciarmos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tenha certeza de ter o Crystal instalado corretamente na sua máquina&lt;/li&gt;
&lt;li&gt;Prepare o editor de código favorito no diretório que foi criado&lt;/li&gt;
&lt;li&gt;Caso não tenha instalado o Crystal ainda clique &lt;a href="https://crystal-lang.org/install"&gt;aqui&lt;/a&gt; para saber mais!
Após abrir seu diretório de trabalho, caso queira iniciar o &lt;code&gt;shards&lt;/code&gt; para criação de um arquivo para controle de projeto, execute em seu terminal:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;shards init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seu arquivo &lt;code&gt;shard.yml&lt;/code&gt; deverá seguir o seguinte formato:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;json-reader&lt;/span&gt;

&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.1.0&lt;/span&gt;

&lt;span class="na"&gt;authors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;João Lanjoni &amp;lt;guto@lanjoni.dev&amp;gt;&lt;/span&gt;

&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;JSON reader&lt;/span&gt;

&lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;teste&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src/main.cr&lt;/span&gt;

&lt;span class="na"&gt;license&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MIT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora crie um diretório chamado &lt;code&gt;src&lt;/code&gt;, nele vamos colocar todo o nosso código trabalhado utilizando Crystal! Crie também um diretório chamado &lt;code&gt;content&lt;/code&gt; na raiz do projeto para conter todos os nossos arquivos em formato &lt;code&gt;JSON&lt;/code&gt;!&lt;br&gt;
Sendo assim, basta adicionar um arquivo no formato &lt;code&gt;JSON&lt;/code&gt; com o nome que desejar no diretório &lt;code&gt;content&lt;/code&gt; e adicionar um arquivo &lt;code&gt;main.cr&lt;/code&gt; no diretório &lt;code&gt;src&lt;/code&gt;, assim, ficaremos com nossa árvore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;json-reader/ 
    ├── content/ 
    │ └── index.json 
    ├── src/ 
    │ └── main.cr 
    └── shard.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Lembrando que o &lt;code&gt;shard.yml&lt;/code&gt; só existe se você iniciou o shards dentro de seu projeto!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Mãos na massa (no teclado)
&lt;/h2&gt;

&lt;p&gt;Primeiramente vamos criar nosso arquivo JSON, por isso, seguindo o template passado acima crie um arquivo &lt;code&gt;.json&lt;/code&gt; dentro do diretório &lt;code&gt;content&lt;/code&gt;! Com ele vamos manipular os valores lá existentes!&lt;br&gt;
Agora abra seu arquivo &lt;code&gt;src/main.cr&lt;/code&gt; no seu editor de código favorito para podermos manipular melhor nosso projeto!&lt;br&gt;
Abrindo seu arquivo primeiramente vamos importar a biblioteca &lt;code&gt;json&lt;/code&gt; para trabalharmos com arquivos neste formato, assim, adicione em seu código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Toda biblioteca pode ser adicionada com o comando &lt;code&gt;require&lt;/code&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para informarmos qual será o arquivo a ser lido, vamos realizar uma simples passagem por argumento/opção ao executar nosso projeto! Assim, caso queira se aprofundar um pouco mais sobre a passagem de argumentos na linha de comando com Crystal clique &lt;a href="https://crystal-lang.org/api/1.8.2/toplevel.html"&gt;aqui&lt;/a&gt;. Dessa forma, vamos salvar o conteúdo do arquivo JSON em uma variável:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"content/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Para recebermos o primeiro argumento/opção utilizaremos o &lt;code&gt;ARGV[0]&lt;/code&gt;, afinal, a posição 0 é a primeira no array de valores passados como opções! O &lt;code&gt;content&lt;/code&gt; no começo significa que precisamos passar apenas o nome do arquivo, afinal, já será buscado um arquivo de mesmo nome no diretório especificado!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Certo, mas, existe ainda o caso do usuário não adicionar nenhuma opção, certo? Neste caso o código nem deve continuar, afinal, se um arquivo JSON não for especificado, logo, não podemos realizar a manipulação! Assim, antes, adicionamos uma simples verificação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"É necessário passar o nome do arquivo como parâmetro!"&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;O tamanho sendo diferente de 1 demonstra que foram passados ou mais de um argumento ou nenhum, por isso, em ambos os casos, devemos rejeitar a execução!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para realizar o &lt;code&gt;parse&lt;/code&gt; de nosso JSON existem algumas formas, vamos começar com a mais simples: JSON de chaves únicas! Veja o JSON de exemplo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"teste"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"teste2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tchau"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Perceba que este formato não possui colchetes em seu início, indicando não ser um array!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para realizar o &lt;code&gt;parse&lt;/code&gt; vamos utilizar uma função nativa do Crystal para realizar a leitura de um JSON e depois convertê-lo em um Hash de Strings!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;hash_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;hash_content&lt;/span&gt; &lt;span class="c1"&gt;# {"teste" =&amp;gt; "oi", "teste2" =&amp;gt; "tchau"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Desta forma vamos montar uma variável com nome &lt;code&gt;hash_content&lt;/code&gt;, tendo em seu conteúdo um hash com chave valor de String para String, trazendo estes dados de um JSON&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Logo, nosso código final será algo como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"json"&lt;/span&gt;

&lt;span class="c1"&gt;# Verificação de argumentos sendo igual a 1&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"É necessário passar o nome do arquivo como parâmetro!"&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Carregando o conteúdo do arquivo JSON&lt;/span&gt;
&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"content/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="c1"&gt;# Transformando os dados do arquivo JSON em um Hash de String =&amp;gt; String&lt;/span&gt;
&lt;span class="n"&gt;hash_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Imprimindo o conteúdo da variável&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;hash_content&lt;/span&gt; &lt;span class="c1"&gt;# {"teste" =&amp;gt; "oi", "teste2" =&amp;gt; "tchau"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos executar de duas formas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Utilizando &lt;code&gt;shards&lt;/code&gt;:
&lt;/h2&gt;

&lt;p&gt;&lt;br&gt;
&lt;code&gt;$ shards run -- content.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Utilizando o próprio &lt;code&gt;crystal&lt;/code&gt;:
&lt;/h2&gt;

&lt;p&gt;&lt;br&gt;
&lt;code&gt;$ crystal run src/main.cr content.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Certo, mas, e se quiséssemos apenas o retorno da chave &lt;code&gt;teste&lt;/code&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;hash_content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"teste"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# oi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim, conseguimos manipular nossos dados no arquivo JSON, podendo trazer as chaves específicas para cada item!&lt;/p&gt;

&lt;h2&gt;
  
  
  Arrays de JSONs
&lt;/h2&gt;

&lt;p&gt;Certo, mas, a maioria dos JSONs que vamos encontrar precisam ser "parseados" utilizando formatos de Array... Como podemos fazer isso? Bom, existem duas formas específicas para realizarmos essa tarefa, bora lá?&lt;/p&gt;

&lt;h3&gt;
  
  
  Primeira forma: Array de Hash
&lt;/h3&gt;

&lt;p&gt;Basicamente vamos montar um array com seu tipo interno sendo hash! Mas, como isso ficaria na prática? Bom, primeiro vou repassar agora o arquivo JSON que estaremos trabalhando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"teste"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fala tropa"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"teste2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eai"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos primeiramente definir que estamos trabalhando com um array, mas, no momento de definir o tipo do array vamos trocar para &lt;code&gt;Hash(String, String)&lt;/code&gt;, veja:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="c1"&gt;# [{"teste" =&amp;gt; "fala tropa"}, {"teste2" =&amp;gt; "eai"}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que basicamente envolvemos o formato de hash anterior no array, correto? Assim podemos trabalhar com nossos arrays de JSONs da forma que preferirmos! Mas, como eu poderia trazer apenas o conteúdo da chave "teste"? Simples, veja dois exemplos abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# {"teste" =&amp;gt; "fala tropa"}&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"teste"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# fala tropa&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim, conseguimos manipular nosso JSON!&lt;/p&gt;

&lt;p&gt;Caso o formato de chave não seja sempre String, podemos ainda criar um &lt;code&gt;alias&lt;/code&gt; para manipular os tipos passados por Hash ou então apenas adicionarmos um operador pipe ("|") demonstrando que o tipo pode variar, sendo assim seria algo como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Segunda forma: File.open
&lt;/h3&gt;

&lt;p&gt;Podemos ainda utilizar o &lt;code&gt;File.open&lt;/code&gt; para abrir um arquivo e trabalhar com seu conteúdo (na qual deixo os créditos para a &lt;a href="https://twitter.com/cherry_ramatis"&gt;cherry&lt;/a&gt; por ter passado na &lt;a href="//twitch.tv/gutolanjoni"&gt;live&lt;/a&gt; e deixado esse detalhe importantíssimo), sem a necessidade da criação de uma variável para realizar esse trabalho (como estávamos fazendo com a variável &lt;code&gt;content&lt;/code&gt;). Veja uma implementação abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"content/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="c1"&gt;# [{"teste" =&amp;gt; "fala tropa"}, {"teste2" =&amp;gt; "eai"}]&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# {"teste" =&amp;gt; "fala tropa"}&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"teste"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# fala tropa&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Neste exemplo realizamos um simples "parse" de valores e atualizamos na variável de nome &lt;code&gt;json&lt;/code&gt;, podendo trabalhar com os valores no mesmo formato que anteriormente!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Assim, nosso projeto completo finaliza na segunda forma! Veja como ficou nosso código finalizado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"json"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"É necessário passar o nome do arquivo como parâmetro!"&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"content/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="c1"&gt;# [{"teste" =&amp;gt; "fala tropa"}, {"teste2" =&amp;gt; "eai"}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Finalização
&lt;/h2&gt;

&lt;p&gt;Com este guia e pequeno artigo você aprendeu a como manipular arquivos JSON e dados vindo de outros arquivos utilizando Crystal, baseando-se no modelo chave-valor que é oferecido, podendo criar comandos, leituras específicas, entre outros tipos de projetos! Para acessar o código desenvolvido neste artigo basta clicar &lt;a href="https://github.com/lanjoni/json-reader-crystal"&gt;aqui&lt;/a&gt;! &lt;br&gt;
Nos vemos na próxima, até mais! Cristalize ainda mais o seu dia! 💎 🖤&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>json</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Why should you learn Crystal?</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Tue, 18 Apr 2023 20:21:00 +0000</pubDate>
      <link>https://dev.to/guto/why-should-you-learn-crystal-5b77</link>
      <guid>https://dev.to/guto/why-should-you-learn-crystal-5b77</guid>
      <description>&lt;p&gt;Have you ever heard of this amazing language called &lt;a href="https://crystal-lang.org/"&gt;Crystal&lt;/a&gt;? Okay, let's understand a little bit about everything this amazing programming language has to offer.&lt;/p&gt;

&lt;p&gt;The purpose of this short article is to talk a little about Crystal and why you might be interested in developing using it.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Crystal?
&lt;/h1&gt;

&lt;p&gt;Being a multi-paradigm programming language, for humans and computers, designed and developed by &lt;a href="https://github.com/asterite"&gt;Ary Borenszweig&lt;/a&gt;, &lt;a href="https://github.com/waj"&gt;Juan Wajnerman&lt;/a&gt;, &lt;a href="https://github.com/bcardiff"&gt;Brian Cardiff&lt;/a&gt;, in addition to more than 480 contributors to date, with syntax inspired by the Ruby language, Crystal stood out for applying concepts of concurrency and general use in a "differentiated" way, using static type checking through a global inference algorithm. Currently in active development, licensed under Apache 2.0.&lt;/p&gt;

&lt;h1&gt;
  
  
  History
&lt;/h1&gt;

&lt;p&gt;With the first works starting in 2011 with the aim of merging the productivity and elegance of Ruby with the speed, efficiency and security of a compiled language, the so-called Joy appears, which was later renamed to Crystal.&lt;/p&gt;

&lt;p&gt;It's first compiler was written in Ruby, but rewritten in Crystal, enabling self-hosting from November 2013, with a first version released in June 2014, in addition to joining the TIOBE index in July 2016. It's first version stable appeared in March 2021, the famous version 1.0!&lt;/p&gt;

&lt;h1&gt;
  
  
  Why is Crystal more efficient?
&lt;/h1&gt;

&lt;p&gt;Simple, Crystal compiles native code using LLVM, excluding dynamic aspects of Ruby. It's advanced global type inference applied in the compiler, combined with &lt;a href="https://crystal-lang.org/reference/1.8/syntax_and_semantics/union_types.html"&gt;union types&lt;/a&gt; creates a sense of a higher-level scripting language more than many other programming languages that can be compared.&lt;/p&gt;

&lt;p&gt;In addition, Crystal has a macro system and supports method and operator overloading. It's concurrency model is inspired by sequential process communication (CSP) implementing green threads called fibers and other concepts inspired by the Go programming language. Another important point is it's automated garbage collection offering a Boehm collector.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to install?
&lt;/h1&gt;

&lt;p&gt;Installation varies for each operating system to be used! You can try installing via your default package manager by searching for the package named &lt;code&gt;crystal&lt;/code&gt; or else follow the &lt;a href="https://crystal-lang.org/install/"&gt;official installation guide&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;If you are using Windows, you can either install via WSL or try the trial version of the official installer for Windows!&lt;/p&gt;

&lt;h1&gt;
  
  
  Shards
&lt;/h1&gt;

&lt;p&gt;Shards is the name of the dependency manager in the Crystal programming language, which by default uses the &lt;code&gt;shard.yml&lt;/code&gt; file to define project settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shards&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.1.0&lt;/span&gt;

&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;openssl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;datanoise/openssl.cr&lt;/span&gt;
     &lt;span class="na"&gt;branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="na"&gt;development_dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;minitest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;git&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/ysbaddaden/minitest.cr.git&lt;/span&gt;
     &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~&amp;gt; 0.3.1&lt;/span&gt;

&lt;span class="na"&gt;license&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MIT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the official repository by clicking &lt;a href="https://github.com/crystal-lang/shards"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Code
&lt;/h1&gt;

&lt;p&gt;Using the &lt;code&gt;.cr&lt;/code&gt; file extension by default, let's create a practical example just showing the basis of a simple "Hello World", an HTTP server and a concurrency model!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello World!
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;"Hello World!"&lt;/span&gt;
&lt;span class="c1"&gt;# or&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello World!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  HTTP server
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"http/server"&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
   &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"text/plain"&lt;/span&gt;
   &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"Hello, got &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Listening on http://127.0.0.1:8080"&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now just access the local page with port "8080" to test!&lt;/p&gt;

&lt;h2&gt;
  
  
  Concurrency Model
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;total_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"*.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
   &lt;span class="n"&gt;spawn&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
     &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
   &lt;span class="n"&gt;total_lines&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;total_lines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Where can I see more about Crystal?
&lt;/h1&gt;

&lt;p&gt;You can read the &lt;a href="https://crystal-lang.org/reference/1.8/index.html"&gt;official documentation&lt;/a&gt;, follow the official language profile on &lt;a href="https://github.com/crystal-lang"&gt;GitHub&lt;/a&gt; and even study my own guide in Portuguese to get started with Crystal: the famous &lt;a href="https://github.com/lanjoni/crystal4noobs"&gt;Crystal4noobs&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>programming</category>
      <category>opensource</category>
      <category>performance</category>
    </item>
    <item>
      <title>Por que você deveria aprender Crystal?</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Tue, 18 Apr 2023 20:13:17 +0000</pubDate>
      <link>https://dev.to/guto/por-que-voce-deveria-aprender-crystal-2c12</link>
      <guid>https://dev.to/guto/por-que-voce-deveria-aprender-crystal-2c12</guid>
      <description>&lt;p&gt;Alguma vez você já ouviu falar dessa incrível linguagem chamada &lt;a href="https://crystal-lang.org/"&gt;Crystal&lt;/a&gt;? Certo, vamos entender um pouco sobre tudo que essa incrível linguagem de programação tem para oferecer. &lt;/p&gt;

&lt;p&gt;O objetivo deste pequeno artigo é falar um pouco sobre Crystal e por quais motivos você poderia se interessar pelo desenvolvimento utilizando-a.&lt;/p&gt;

&lt;h1&gt;
  
  
  O que é Crystal?
&lt;/h1&gt;

&lt;p&gt;Sendo uma linguagem de programação multi-paradigma, para humanos e computadores, desenhada e desenvolvida por &lt;a href="https://github.com/asterite"&gt;Ary Borenszweig&lt;/a&gt;, &lt;a href="https://github.com/waj"&gt;Juan Wajnerman&lt;/a&gt;, &lt;a href="https://github.com/bcardiff"&gt;Brian Cardiff&lt;/a&gt;, além de mais de 480 colaboradores até o momento, tendo sintaxe inspirada na linguagem Ruby, Crystal se destacou por aplicar conceitos de concorrência e uso geral de uma maneira "diferenciada", utilizando verificação estática de tipos por meio de um algoritmo de inferência global. Atualmente em desenvolvimento ativo, tendo como licença a Apache 2.0.&lt;/p&gt;

&lt;h1&gt;
  
  
  História
&lt;/h1&gt;

&lt;p&gt;Com seus primeiros trabalhos se iniciando em 2011 com o objetivo de mesclar a produtividade e elegância de Ruby com a velocidade, eficiência e segurança de uma linguagem compilada, surge a chamada Joy, que posteriormente foi renomeada para Crystal.&lt;/p&gt;

&lt;p&gt;Seu primeiro compilador foi escrito em Ruby, mas, reescrito em Crystal, possibilitando uma auto-hospedagem a partir de novembro de 2013, tendo uma primeira versão lançada em junho de 2014, além de ingressar no índice TIOBE em julho de 2016. Sua primeira versão estável surgiu em março de 2021, a famosa versão 1.0!&lt;/p&gt;

&lt;h1&gt;
  
  
  Por que Crystal é mais eficiente?
&lt;/h1&gt;

&lt;p&gt;Simples, Crystal compila o código nativo usando LLVM, excluindo aspectos dinâmicos do Ruby. Sua inferência de tipo global avançada aplicada no compilador, combinada com &lt;a href="https://crystal-lang.org/reference/1.8/syntax_and_semantics/union_types.html"&gt;tipos de união&lt;/a&gt; cria uma sensação de uma linguagem de script de maior nível do que muitas outras linguagens de programação que podem ser comparadas. &lt;/p&gt;

&lt;p&gt;Além disso, Crystal possui um sistema de macro e suporta sobrecarga de métodos e operadores. Seu modelo de concorrência é inspirado na comunicação de processos sequenciais (CSP) implementando threads verdes (tradução literal de "green threads") chamadas de fibras (tradução literal de "fibers") e outros conceitos inspirados na linguagem de programaçao Go. Outro ponto importante é sua coleta de lixo automatizada oferecendo um coletor Boehm.&lt;/p&gt;

&lt;h1&gt;
  
  
  Como instalar?
&lt;/h1&gt;

&lt;p&gt;A instalação varia para cada sistema operacional a ser utilizado! Você pode tentar instalar pelo seu gerenciador de pacotes padrão buscando pelo pacote nomeado &lt;code&gt;crystal&lt;/code&gt; ou então seguir o &lt;a href="https://crystal-lang.org/install/"&gt;guia oficial de instalação&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Caso você esteja utilizando Windows, você pode instalar tanto pelo WSL quanto experimentar a versão de testes do instalador oficial para Windows!&lt;/p&gt;

&lt;h1&gt;
  
  
  Shards
&lt;/h1&gt;

&lt;p&gt;Shards é o nome do gerenciador de dependências da linguagem de programação Crystal, que utiliza por padrão o arquivo &lt;code&gt;shard.yml&lt;/code&gt; para definir configurações de projeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shards&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.1.0&lt;/span&gt;

&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;openssl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;datanoise/openssl.cr&lt;/span&gt;
    &lt;span class="na"&gt;branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="na"&gt;development_dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;minitest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;git&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/ysbaddaden/minitest.cr.git&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~&amp;gt; 0.3.1&lt;/span&gt;

&lt;span class="na"&gt;license&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MIT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você pode ver o repositório oficial clicando &lt;a href="https://github.com/crystal-lang/shards"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Código
&lt;/h1&gt;

&lt;p&gt;Utilizando por padrão a extensão de arquivos &lt;code&gt;.cr&lt;/code&gt; vamos criar um exemplo prático apenas mostrando a base de um simples "Hello World", um servidor HTTP e um modelo de concorrência, vamos lá?&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello World!
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;"Hello World!"&lt;/span&gt;
&lt;span class="c1"&gt;# ou&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello World!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Servidor HTTP
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"http/server"&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"text/plain"&lt;/span&gt;
  &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"Hello, got &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Listening on http://127.0.0.1:8080"&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora basta acessar a página local com porta "8080" para testarmos!&lt;/p&gt;

&lt;h2&gt;
  
  
  Modelo de Concorrência
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;total_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"*.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;spawn&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_lines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;total_lines&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;total_lines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Onde posso ver mais sobre Crystal?
&lt;/h1&gt;

&lt;p&gt;Você pode ler a &lt;a href="https://crystal-lang.org/reference/1.8/index.html"&gt;documentação oficial&lt;/a&gt;, seguir o perfil oficial da linguagem no &lt;a href="https://github.com/crystal-lang"&gt;GitHub&lt;/a&gt; e até mesmo estudar meu próprio guia em português de introdução ao Crystal: o famoso &lt;a href="https://github.com/lanjoni/crystal4noobs"&gt;Crystal4noobs&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>programming</category>
      <category>opensource</category>
      <category>performance</category>
    </item>
    <item>
      <title>Taking the terminal to the next level: customizing features</title>
      <dc:creator>guto</dc:creator>
      <pubDate>Fri, 06 Jan 2023 03:12:49 +0000</pubDate>
      <link>https://dev.to/guto/taking-the-terminal-to-the-next-level-customizing-features-3eck</link>
      <guid>https://dev.to/guto/taking-the-terminal-to-the-next-level-customizing-features-3eck</guid>
      <description>

&lt;h1&gt;
  
  
  Table of contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Presentation&lt;/li&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;What is terminal?&lt;/li&gt;
&lt;li&gt;
Some shell types

&lt;ol&gt;
&lt;li&gt;Bash&lt;/li&gt;
&lt;li&gt;Zsh&lt;/li&gt;
&lt;li&gt;Fish&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

Customizations for each shell

&lt;ol&gt;
&lt;li&gt;Configuration files&lt;/li&gt;
&lt;li&gt;
Visual

&lt;ol&gt;
&lt;li&gt;Bash and oh-my-bash&lt;/li&gt;
&lt;li&gt;Zsh and oh-my-zsh&lt;/li&gt;
&lt;li&gt;Fish, oh-my-fish, fisher and z&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt; Nerd Fonts
&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ol&gt;




&lt;h1&gt;
  
  
  Presentation
&lt;/h1&gt;

&lt;p&gt;If you are interested in starting to use Linux in 2023, or if you already use it and want to customize and maximize your performance using the terminal, know that you are in the right place! This guide intends to show how you can use native tools from the terminal itself and customize it to make it your own, increasing your productivity and stepping out of your comfort zone!&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;The terminal has been part of developers' day-to-day life for a long time, and it is possible to say that the evolution of computers to what we know today only became possible because, way back, the terminal itself was created, with that little face of "a black screen with several small letters", which, during the time when we didn't have a graphical interface, it was our means of communication with the computer.&lt;/p&gt;

&lt;p&gt;Currently, we live in a time when technology is part of practically everyone's life, so we have become accustomed to certain interfaces and ways of solving different problems in our daily lives, resulting in an effect that makes cutting-edge technology a reality. increasingly simple to be understood by human eyes according to the levels of abstractions that are added to it.&lt;/p&gt;

&lt;p&gt;Therefore, it is not so difficult to find someone who does not know how or does not like to use a computer via a terminal, which is characterized not as a negative phenomenon, but as a phenomenon resulting from the great reach of technology in people's lives, enabling the use of them without the need for large studies behind. Technology is in our midst and is part of our daily lives in such an intertwined way that many times we are not even able to notice it.&lt;/p&gt;

&lt;p&gt;Punctuating this advance in technology, today, I will show you how the terminal has also evolved a lot, becoming a powerful tool, making the user who dominates the terminal and its tools become totally independent and productive during the days as a developer.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is terminal?
&lt;/h1&gt;

&lt;p&gt;Emerging at the beginning of the computing era, existing until today as an essential tool in an operating system, basically, the terminal would be nothing less than the first interface that enabled human-computer interaction, in which a sequence of commands could be sent (input), then it is processed (processing), and it returns a response (output).&lt;/p&gt;

&lt;p&gt;The terminal "has" the appearance of a black screen even when waiting for a command entry (the word was placed in quotes because currently, not necessarily a terminal is like that, after all, it can be customized in several ways and this will be shown here later) . He is the user's contact with the "shell", and uses a command interpreter for the "shell".&lt;/p&gt;

&lt;p&gt;Shell is nothing more than the layer that acts as an "interlocutor" between the user and the operating system kernel, being responsible for validating and sending commands to the kernel, which is responsible for managing our hardware.&lt;/p&gt;

&lt;center&gt;
    
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.stack.imgur.com%2FZnlqz.jpg" alt="Image demonstrating the shell wrapping the kernel while the user sends input directly to the shell" width="800" height="400"&gt;Image demonstrating the process of user input and sending the instruction to the Kernel
        
    
&lt;/center&gt;

&lt;p&gt;Currently, in most Linux distributions, the terminal is found in the form of an external emulator, running as a common application in which many times some users do not even realize that we can install several other emulators that use GPU acceleration (a powerful tool for users with more "powerful" GPUs), simple visual customization, font customization, among many other possible customizations.&lt;/p&gt;

&lt;p&gt;Using the default terminal emulator of your Linux distribution is your choice, it depends on which type of emulator you are most comfortable with, so the choice itself is up to you! I will present some customizations of Shell interpreters, moving on to a presentation of several terminal emulators that can be installed both in Linux distributions and other Unix-based operating systems, such as macOS and FreeBSD for example.&lt;/p&gt;

&lt;p&gt;As much as it makes the text longer, the basic explanations of the operation and history of the terminal are necessary for a complete understanding, allowing you to start from that point to advance your knowledge.&lt;/p&gt;

&lt;h1&gt;
  
  
  Some shell types
&lt;/h1&gt;

&lt;p&gt;There are several types of command interpreters, but I will mention three main ones that you can choose to use and customize, starting from its purest interface, until we reach a point where you will feel comfortable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bash
&lt;/h2&gt;

&lt;p&gt;Used in several Linux distributions as a default command interpreter, Bash is currently maintained by the GNU project and the Free Software Foundation. Bash already has a very pleasant interface when compared to other interpreters from the GNU project itself, such as "sh" for example, which is currently found as a standard command interpreter for distributions without a native graphical interface for installation (as in some servers), or then on other Unix-based operating system projects such as FreeBSD.&lt;/p&gt;

&lt;p&gt;Widely spread and, I believe, the most used command interpreter in Linux distributions, bash may be the perfect choice for you. Its appearance after installation can be found in different ways, but currently there are two main ones that we can highlight, which are similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[guto@turing ~]$

guto@turing:~ $
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Zsh
&lt;/h2&gt;

&lt;p&gt;Emerging in the 1990s, zsh has caught the eye of many users over the years for being a slightly different shell than Bash. Its appearance and functionality after installation is much simpler than bash, but after a lot of customization it can become extremely powerful.&lt;/p&gt;

&lt;p&gt;Initially being distributed with a license respecting the Berkeley standards, zsh had its skyrocket in use in macOS systems when Apple in 2020 officially switched the default shell of its operating system for bash users to zsh due to some issues involving the GNU GPL v3.0 license.&lt;/p&gt;

&lt;p&gt;Starting zsh after installation is very simple: if you already have the zsh configuration file (it could be .zshrc for example), it will start with an appearance bringing only the machine name (very similar to sh), but, if you don't have this file yet, it will display a message alerting you that this file does not exist, in which case, pressing "0" will automatically create this empty file just to not return this message anymore. The initial appearance of zsh looks something 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;turing%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fish
&lt;/h2&gt;

&lt;p&gt;With its initial release in 2005, fish shell has pleased many users around the world mainly due to its ease of customization, with native functions including command autocompletion with automatic suggestions, pre-configured visuals, among other diverse features.&lt;/p&gt;

&lt;p&gt;The fish shell is also free software and includes parts of the GNU GPL v2.0 license, OpenBSD license, ISC license and NetBSD license, and can be evaluated in its repository at &lt;a href="https://github.com/fish-shell%20/fish-shell" rel="noopener noreferrer"&gt;github&lt;/a&gt;. In most cases the fish shell will have to be installed externally, after all, not all distributions have it installed by default.&lt;/p&gt;

&lt;p&gt;Its default appearance is nice and bash-like, differing by having a "fish" instead of a simple dollar sign ("$") for non-root users. Its default appearance looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;guto@turing ~&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fish shell can have direct integration with your terminal emulator, allowing its customization directly from a page generated locally by executing the "fish_config" command, in which it is possible to customize the colors, functions, shortcuts, among other diverse functionalities. The generated screen looks like the image below:&lt;/p&gt;

&lt;center&gt;
    
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.jpalardy.com%2Fassets%2Ffish-shell%2Fweb_config.png" alt="Image of the locally generated fish shell configuration screen after running the fish_config command" width="800" height="642"&gt;Showing the fish shell configuration screen with the fish_config command
        
    
&lt;/center&gt;

&lt;h1&gt;
  
  
  Customizations for each shell
&lt;/h1&gt;

&lt;p&gt;Now, let's move on to configuring your chosen command interpreter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration files
&lt;/h2&gt;

&lt;p&gt;The configuration files of each shell may vary in name, but we will address their names and how to access them, and what are the main functions that we can customize and use in our daily lives, such as creating an alias.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bash: .bashrc or .bash_profile&lt;/li&gt;
&lt;li&gt;Zsh: .zshrc or .zsh_profile&lt;/li&gt;
&lt;li&gt;Fish: ~/.config/fish/config.fish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open the file in your favorite text editor, and you may find a series of instructions that you didn't know or even had no idea what they would be for.&lt;/p&gt;

&lt;p&gt;In this file, go to the end of it so we don't have the possibility of damaging its content or even compromising some function that you like. On the last line, we can add a series of commands that our interpreter must understand.&lt;/p&gt;

&lt;p&gt;The first of the instructions to be created will be an example of "alias", which would be nothing more than a "nickname" for some sequence of commands that we want to execute. In this case I will create an alias to install a package with root permissions (the famous "sudo"). Our alias will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias install&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sudo apt install"&lt;/span&gt; &lt;span class="c"&gt;# For Debian based distributions&lt;/span&gt;
&lt;span class="nb"&gt;alias install&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sudo dnf install"&lt;/span&gt; &lt;span class="c"&gt;# For Red Hat based distributions&lt;/span&gt;
&lt;span class="nb"&gt;alias install&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sudo pacman -Sy"&lt;/span&gt; &lt;span class="c"&gt;# For Arch Linux based distributions&lt;/span&gt;

&lt;span class="c"&gt;# For macOS&lt;/span&gt;
&lt;span class="nb"&gt;alias install&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"brew install"&lt;/span&gt; &lt;span class="c"&gt;# If you are using Homebrew as a package manager&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please, pay attention to which distribution you are adding the command to, after all, each one has its own package manager, right? What do you think of an article in the future talking a little about the structure of a Linux operating system?&lt;/p&gt;

&lt;p&gt;The structure of creating an alias is very simple and respects the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;"[command to be executed when calling this alias]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The use of aliases on a day-to-day basis is powerful and can make it much easier when it comes to productivity, which we can expand to a series of functions that we can install and customize within our configuration file, in which we are going to customize its appearance now.&lt;/p&gt;

&lt;p&gt;Did you notice that the fish shell has a slightly different file? Well, it accepts slightly different instructions in its use, but, in order not to extend myself so much, know that you can access the &lt;a href="https://fishshell.com/docs/current/" rel="noopener noreferrer"&gt;official fish shell documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visual
&lt;/h2&gt;

&lt;p&gt;Now you know where your command interpreter configuration file is, so you know where you can create native functions interpreted in Shell for your day-to-day! In this way, we are now going to a visual customization of each shell.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bash and oh-my-bash
&lt;/h3&gt;

&lt;p&gt;Going to the appearance, we know that bash has an appearance that may not please everyone, but that can be customized and for that there are two main ways that will be presented: using the standard command for creating appearances or through a tool that facilitates our customization, called "oh-my-bash", being maintained by an amazing community.&lt;/p&gt;

&lt;p&gt;The line below will show how the appearance of your input line in bash can be modified by changing the PS1, responsible for leaving it with this more pleasant look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\u@\h:\[\e[01;32m\]\w\[\e[0m\]\$ '&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically it leaves a "user@host:path/to/directory $" with the hostname in green! To change the foreground colors it was necessary to add the code snippet that contains some numbers inside, the color code respecting the ANSI table for bash! An important detail to remember is that according to your terminal emulator these colors may contain different shades that you can customize yourself!&lt;/p&gt;

&lt;center&gt;
    
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.stack.imgur.com%2FPRUhI.png" alt="Image with ANSI color table shown by terminal" width="800" height="400"&gt;Table of colors and ANSI codes displayed by the terminal
        
    
&lt;/center&gt;

&lt;p&gt;Support for the so-called "true color", which would be the 256 RGB colors varies according to the terminal emulator you are using.&lt;/p&gt;

&lt;p&gt;Right, but what if I want to perform a simpler customization without the need to change color codes or already use some existing customization, can I do it? The answer is yes, you can, and the oh-my-bash project came about for just that purpose!&lt;/p&gt;

&lt;p&gt;Accessing the &lt;a href="https://ohmybash.nntoan.com/" rel="noopener noreferrer"&gt;official website&lt;/a&gt; you can browse the documentation, contribute and view the themes already published, and their installation can be done using curl or wget. If you haven't installed any of the two packages yet, just use the following commands:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;wget&lt;/em&gt;&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;sudo apt install wget # For Debian based distributions
sudo dnf install wget # For Red Hat based distributions
sudo pacman -Sy wget # For Arch Linux based distributions

# For macOS
brew install wget # If you are using Homebrew as a package manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;curl&lt;/em&gt;&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;sudo apt install curl # For Debian based distributions
sudo dnf install curl # For Red Hat based distributions
sudo pacman -Sy curl # For Arch Linux based distributions

# Para macOS
brew install curl # If you are using Homebrew as a package manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing, just open a new tab of your terminal emulator to update and you will be able to see that the default theme has been changed! To browse between the oh-my-bash themes, just click on the themes tab and access the &lt;a href="https://github.com/ohmybash/oh-my-bash/wiki/Themes" rel="noopener noreferrer"&gt;repository&lt;/a&gt; which presents all the themes and choose one of your interest.&lt;/p&gt;

&lt;p&gt;Once you choose, just open the bash configuration file (.bashrc or .bash_profile) and right at the beginning of the file you will see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;OSH_THEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"font"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just change the name "font" to the name of the theme you want to put (without removing the quotes), and that's it! Now just restart your terminal emulator or open a new tab and you'll be in your new look! Did you like it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Zsh and oh-my-zsh
&lt;/h3&gt;

&lt;p&gt;The configuration of the look of zsh shell starts from the same principle as bash with the creation of a variable "PS1" that can be accessed in the tab above.&lt;/p&gt;

&lt;p&gt;oh-my-zsh is a project maintained by a community just like the oh-my-bash project, however, it has some differences that make this community huge, ranging from complete documentation to even a store of products from the which we can purchase t-shirts, stickers, among others.&lt;/p&gt;

&lt;p&gt;Accessing the &lt;a href="https://ohmyz.sh/" rel="noopener noreferrer"&gt;official website&lt;/a&gt; project we can view a simple installation guide using curl or wget, in which it was previously shown how we can install both tools.&lt;/p&gt;

&lt;p&gt;After installation, we can easily browse the &lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Themes" rel="noopener noreferrer"&gt;oh-my-zsh themes&lt;/a&gt; tab (which is also available on the website) and choose a theme from our preference that, when opening our configuration file (.zshrc or .zsh_profile for example) we will come across something similar at the beginning of our configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;ZSH_THEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"robbyrussell"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To change the theme and choose the theme of your personal taste, just change the name that is between quotes to the name of the theme you want to install and then open a new tab of your terminal emulator to boot with the new theme working normally!&lt;/p&gt;

&lt;h3&gt;
  
  
  Fish, oh-my-fish, fisher and z
&lt;/h3&gt;

&lt;p&gt;The fish shell, as mentioned earlier, has some additional settings that can be used to customize our shell and in this case, we can handle and manipulate plugins within it.&lt;/p&gt;

&lt;p&gt;The fish configuration file is found in the path "~/.config/fish/config.fish" and we can customize the entry using "PS1", just like in bash and zsh. If you want a slightly nicer interface to customize its operation, just use the "fish_config" command, which will open a mini local server so that your changes take effect in real time.&lt;/p&gt;

&lt;p&gt;Like oh-my-bash and oh-my-zsh, oh-my-fish came up with the possibility for users to use pre-defined themes published and maintained by the community as a way to provide a better use of the fish shell. Oh-my-fish does not have an official page, but its &lt;a href="https://github.com/oh-my-fish/oh-my-fish" rel="noopener noreferrer"&gt;repository&lt;/a&gt; is published on GitHub and can be installed in several ways, but with the simple installation script we will use the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | fish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have any problems with the installation, just access the official GitHub page of oh-my-fish and install by directly cloning the official repository, as shown in the README of the project.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/oh-my-fish/oh-my-fish/blob/master/docs/Themes.md" rel="noopener noreferrer"&gt;themes&lt;/a&gt; can be accessed and chosen according to your taste and their installation can be done with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;omf &lt;span class="nb"&gt;install &lt;/span&gt;URL &lt;span class="c"&gt;# To enter the theme URL&lt;/span&gt;
omf &lt;span class="nb"&gt;install &lt;/span&gt;user/repo &lt;span class="c"&gt;# To enter the theme repository&lt;/span&gt;
omf &lt;span class="nb"&gt;install &lt;/span&gt;name &lt;span class="c"&gt;# To enter the theme name from the list of pre-installed themes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, starting with the usability customization of the fish shell we can mention &lt;a href="https://github.com/jorgebucaran/fisher" rel="noopener noreferrer"&gt;fisher&lt;/a&gt;, which is a plugin manager for the fish shell, being used to install several repositories with functionalities incredible things that fish shell can offer.&lt;/p&gt;

&lt;p&gt;To install fisher just run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sL&lt;/span&gt; https://git.io/fisher | &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; fisher &lt;span class="nb"&gt;install &lt;/span&gt;jorgebucaran/fisher
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installed you can check a &lt;a href="https://github.com/jorgebucaran/awsm.fish" rel="noopener noreferrer"&gt;list of plugins&lt;/a&gt; that shows several that are used by the community.&lt;/p&gt;

&lt;p&gt;The big icing on the cake comes now, with the plugins being able to be customized and their appearance being unique: &lt;a href="https://github.com/jethrokuan/z" rel="noopener noreferrer"&gt;z&lt;/a&gt;. That's right, this name, the "z" has the function of working to record the directories you visit and create shortcuts that facilitate your navigation within your operating system. To install z with fisher just run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fisher &lt;span class="nb"&gt;install &lt;/span&gt;jethrokuan/z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you can start using your terminal emulator normally, until it manages to register repetitive entries in a directory to create several shortcuts. If in doubt, z's &lt;a href="https://github.com/jethrokuan/z/blob/master/man/man1/z.md" rel="noopener noreferrer"&gt;manual&lt;/a&gt; can still be accessed on GitHub.&lt;/p&gt;

&lt;p&gt;If you want more extensive configurations involving the fish shell, I recommend watching Takuya Matsuyama's channel called "&lt;a href="https://www.youtube.com/@devaslife" rel="noopener noreferrer"&gt;devaslife&lt;/a&gt;" and a specific video in which he shows &lt;a href="https://youtu.be/KKxhf50FIPI" rel="noopener noreferrer"&gt;how to configure the fish shell&lt;/a&gt; in your daily life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nerd Fonts
&lt;/h2&gt;

&lt;p&gt;In our daily lives, many times we will find several special characters or symbols formed that, when we type, do not form exactly what we would like. A practical example would be when we're writing our code and the "!=" doesn't look like it does in math, or the "-&amp;gt;" doesn't look that much like an arrow.&lt;/p&gt;

&lt;p&gt;It was from this need that "Nerd Fonts" emerged, with the aim of supplying and making our code editor look cooler, working in our terminal and making special symbols understood and presented in the expected way.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.nerdfonts.com" rel="noopener noreferrer"&gt;homepage&lt;/a&gt; has a link to the &lt;a href="https://github.com/ryanoasis/nerd-fonts" rel="noopener noreferrer"&gt;offiical repository&lt;/a&gt; of the project, showing its releases and updates with new fonts. To install the fonts is very simple: you can install by downloading the zipped files and installing the fonts, or, install by your package manager.&lt;/p&gt;

&lt;p&gt;The number of symbols that these fonts can reach is enormous, allowing for several customizations.&lt;/p&gt;

&lt;center&gt;
    
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.nerdfonts.com%2Fassets%2Fimg%2Fsankey-glyphs-combined-diagram.png" alt="Image demonstrating the compatibility of 'Nerd Fonts' fonts compared with various icons and symbols" width="800" height="552"&gt;Comparison of "Nerd Fonts" with various icons and symbols and their compatibility
        
    
&lt;/center&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The use of the terminal in the day-to-day of the developer can be useful in infinite ways. Knowing how to be independent and being able to use the terminal is a job that requires dedication, but which is certainly worth every second of learning.&lt;/p&gt;

&lt;p&gt;The terminal is a powerful tool and may be the only one a developer can use in their daily lives as long as they know how to use it correctly.&lt;/p&gt;

&lt;p&gt;Customizing the terminal is not a waste of time, it's a learning process to make your work environment more comfortable and accessible to your personal tastes, making you feel satisfied.&lt;/p&gt;

&lt;p&gt;Regardless of the shell you choose, how you customize it and which terminal emulator you like, I hope this guide has helped you and added something new to your learning experience.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
