<?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: Vahid Dejwakh</title>
    <description>The latest articles on DEV Community by Vahid Dejwakh (@dej).</description>
    <link>https://dev.to/dej</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%2F459801%2Fb8cf6557-78d2-4122-8521-f582d35cba0a.jpeg</url>
      <title>DEV Community: Vahid Dejwakh</title>
      <link>https://dev.to/dej</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dej"/>
    <language>en</language>
    <item>
      <title>Docker and the rise of microservices</title>
      <dc:creator>Vahid Dejwakh</dc:creator>
      <pubDate>Mon, 14 Jun 2021 12:53:00 +0000</pubDate>
      <link>https://dev.to/dej/docker-and-the-rise-of-microservices-16lc</link>
      <guid>https://dev.to/dej/docker-and-the-rise-of-microservices-16lc</guid>
      <description>&lt;h1&gt;
  
  
  &lt;em&gt;What is Docker, What are microservices, and Why should we care?&lt;/em&gt;
&lt;/h1&gt;

&lt;p&gt;This article was originally published &lt;a href="https://vahid.blog/post/2021-06-13-docker-and-the-rise-of-microservices/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As applications grow in use, the ability to scale becomes paramount. The solution often is to divide your codebase from a single monolith into multiple microservices. Why is Docker a key component in this new architecture, and what does this all even mean?&lt;/p&gt;

&lt;h2&gt;
  
  
  I. From Monolith to Microservices
&lt;/h2&gt;

&lt;p&gt;Before the rise of complex and ubiquitous online services like Google, Facebook, Amazon, Netflix, and YouTube, the standard way to deploy a web application was to have &lt;em&gt;one&lt;/em&gt; central codebase that handled everything, from user authentication to interacting with multiple databases to processing payments.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzfc4eq5s4xmsjo4ts4p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzfc4eq5s4xmsjo4ts4p.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see from image A) on the left above, all the business logic was tightly coupled in the same application, including the logic that handles interactions with database(s).&lt;/p&gt;

&lt;p&gt;This behemoth application is called a monolith.&lt;/p&gt;

&lt;p&gt;The monolith architecture makes growing and scaling an application more difficult. While a small or even medium-sized monolithic codebase can be copied and deployed on multiple application servers distributed geographically, larger and larger monoliths face challenges that make this process less and less appealing.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Requires high level of coordination
&lt;/h3&gt;

&lt;p&gt;There are several reasons why deploying and growing a large monolith is difficult. First, there's the coordination aspect. Teams responsible for different parts of the application have to make sure that their changes to the codebase are done harmoniously without either creating conflicts with or worse, causing errors to another part of the application.&lt;/p&gt;

&lt;p&gt;This requires significant coordination and communication, but also reduces the speed at which updates can be made.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Costly redeployments means slower upkeep
&lt;/h3&gt;

&lt;p&gt;Another problem is that every single change to the monolith, no matter how small, requires redeploying the entire codebase. This can make updates so taxing and take so long that they can only happen occasionally, which means responding to changes or adding more features also takes more time.&lt;/p&gt;

&lt;p&gt;As the codebase grows, the interval between each update may therefore also grow, as more effort goes into consolidating many updates into the same deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Higher learning curve
&lt;/h3&gt;

&lt;p&gt;Another major downside of large monoliths is that onboarding new engineers is challenging and requires more time. In order to understand how to update, fix, add, or otherwise troubleshoot a feature, an engineer may need to understand how the entire system works. If we're dealing with several thousand lines of code, this is manageable. But multiply this by a thousand, and it becomes almost impossible.&lt;/p&gt;

&lt;p&gt;This higher learning curve means that it's more expensive to hire and add engineers to the team, since they must spend more weeks in training before they can actually start to be productive.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. One language for all
&lt;/h3&gt;

&lt;p&gt;Another problem of a monolith is that it needs to be written in the same backend programming language--whether that's Node.js, Ruby, Go, Python, Rust, PHP, Java, etc.&lt;/p&gt;

&lt;p&gt;Languages all have tradeoffs: some are better for certain use cases over others. For example, Node.js's use of JavaScript and its large, prolific community make it ideal for small teams working on small to mid-sized applications or microservices, but its single-threaded V8 engine makes it not as efficient as Go, a master of concurrency thanks to its ability to use multiple channels, and the efficiency gains from being a compiled language.&lt;/p&gt;

&lt;p&gt;With a monolith, you are unable to take advantage of the strengths of each language, and you have to accept the entire language for every segment of your application--even if another language might actually be better suited for a particular segment.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. One bug means the entire application is down
&lt;/h3&gt;

&lt;p&gt;Another problem of putting all your eggs in one monolith application is that if any part of the application fails, the entire system is down.&lt;/p&gt;

&lt;p&gt;Yes, you can &lt;em&gt;and should&lt;/em&gt; try to handle exceptions as much as possible, but you can't always predict how your code will behave in production.&lt;/p&gt;

&lt;p&gt;When any piece fails, the entire system goes down.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Inefficient growth
&lt;/h3&gt;

&lt;p&gt;Finally, the last main reason monoliths are not well suited for growth has to do with the fact that if &lt;em&gt;one aspect of the application&lt;/em&gt; needs to be scaled, then the entire application--including parts that don't handle much traffic--must also be scaled.&lt;/p&gt;

&lt;p&gt;It's like a situation where a family has a two year old, an eight year old, and a twenty year old at dinner, and the twenty year old goes through and finishes his meal very fast. Instead of allowing the twenty year old to help himself to more food, you, the parent, pour an additional 100% more food on every child's plate.&lt;/p&gt;

&lt;p&gt;Some of that additional food is unnecessary and will go to waste!&lt;/p&gt;

&lt;p&gt;Wouldn't it be better to be able to target each child's needs individually, irrespective of the others?&lt;/p&gt;

&lt;h2&gt;
  
  
  II. Microservices To the Rescue
&lt;/h2&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzfc4eq5s4xmsjo4ts4p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzfc4eq5s4xmsjo4ts4p.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's get back to the image above, and imagine that our monolith application in A) handled:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Showing and searching our company's &lt;strong&gt;inventory&lt;/strong&gt; to the customer (e.g. the red heart shape in Martin Fowler's diagram),&lt;/li&gt;
&lt;li&gt;Processing &lt;strong&gt;payments&lt;/strong&gt; for an order (e.g. the green X), and&lt;/li&gt;
&lt;li&gt;Tracking &lt;strong&gt;shipments&lt;/strong&gt; (e.g. the grey blob).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As the diagram shows, all of these might require interactions with a database.&lt;/p&gt;

&lt;p&gt;The microservices architecture in B) would instead break each of these services up into separate, independent applications, each with its own database, and each able to receive requests and respond with some information.&lt;/p&gt;

&lt;p&gt;These microservices would then be independently scalable, updatable, and could be written in a different language entirely. They can communicate with each other over HTTP through REST-ful APIs, or some other agreed protocol.&lt;/p&gt;

&lt;p&gt;The diagram shows, as an example, how the inventory service (the red heart shape) was scaled to two instances, perhaps because more people just search the inventory without actually purchasing. This architecture would allow that, without forcing us to also scale the other services.&lt;/p&gt;

&lt;p&gt;Organizationally, teams could be responsible for separate services, and as long as they do not change the format of inputs or outputs of the service, they can push updates without checking with other teams.&lt;/p&gt;

&lt;p&gt;And thanks to microservices being independent of each other, even if the shipment service goes down, customers can still look at the inventory and make a purchase.&lt;/p&gt;

&lt;h2&gt;
  
  
  III. Tradeoffs &amp;amp; New Problems
&lt;/h2&gt;

&lt;p&gt;We can now appreciate why microservices are becoming more prevalent. So we should just convert every application to a microservices architecture, right?&lt;/p&gt;

&lt;p&gt;No, of course not. For most applications, from startups to mid-size, a monolith works fine and is probably actually preferable. That's because just like everything else in tech, the microservices solution now introduces its own set of problems.&lt;/p&gt;

&lt;p&gt;Monoliths are much simpler to understand and debug; microservices introduce more complexity. Monoliths tend to be faster, since internal function calls can happen synchronously. Now, as a result of communicating over APIs, the microservices system introduces latency and security issues.&lt;/p&gt;

&lt;p&gt;With so many different services, deployed on so many servers worldwide, how do we deal with versioning? How do we deploy systematically? How can we automatically spin up a new instance of a service that we need to scale?&lt;/p&gt;

&lt;h2&gt;
  
  
  IV. Introducing Docker
&lt;/h2&gt;

&lt;p&gt;We're finally at a point where we can appreciate Docker.&lt;/p&gt;

&lt;p&gt;At its core, Docker facilitates the process of duplicating and starting an application in the same exact configured environment everytime.&lt;/p&gt;

&lt;p&gt;A Docker &lt;em&gt;container&lt;/em&gt; is an environment in which a bundled application runs the same versions of every layer wherever deployed.&lt;/p&gt;

&lt;p&gt;This means that any new application or microservice can now more easily be spun up to run and behave exactly the same way as the original.&lt;/p&gt;

&lt;p&gt;A container is different from a virtual private server (VPS) because it does not include the operating system layer, so it's smaller in size (about 10 to 100X), and more easily deployable. While a VPS might take 3 to 10 seconds to boot on a relaunch, a server running a container can reboot the container's application packages in less than a second.&lt;/p&gt;

&lt;p&gt;Let's go through a quick overview of the Docker ecosystem and some of the most important components and terminal commands.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy43t96z8g0awrm45s2c0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy43t96z8g0awrm45s2c0.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, a file named &lt;strong&gt;[1] 'Dockerfile'&lt;/strong&gt; serves as a config file necessary to build &lt;strong&gt;[2] a Docker image&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This image can then be shared remotely via either &lt;strong&gt;[3] a private registry&lt;/strong&gt; (e.g. AWS) or &lt;strong&gt;[4] Docker Hub&lt;/strong&gt;, which is publicly accessible and contains the official images of commonly used software and services.&lt;/p&gt;

&lt;p&gt;To pull an image from or push an image to any remote service, and generally to run any number of container(s), the &lt;strong&gt;[5] Docker Daemon&lt;/strong&gt; must first be installed and running on the end machine.&lt;/p&gt;

&lt;p&gt;The developer interacts with the Daemon through either a &lt;strong&gt;[6] CLI or GUI client&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An image is used to create &lt;strong&gt;[7] container&lt;/strong&gt; instances, which can start and stop to run.&lt;/p&gt;

&lt;p&gt;Each running container must be bound to a particular &lt;strong&gt;[8] host port&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Containers that need to communicate together can be run inside the same &lt;strong&gt;[9] Isolated Docker Network&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  V. Summing up
&lt;/h2&gt;

&lt;p&gt;We've seen the problems of large monolith applications, and why they are more difficult to scale.&lt;/p&gt;

&lt;p&gt;We discussed the advantages of microservices architectures, and why they are growing in popularity.&lt;/p&gt;

&lt;p&gt;We also understand the tradeoffs of this new approach to writing software applications, and why monoliths are still probably better suited for small to mid-sized applications.&lt;/p&gt;

&lt;p&gt;Finally, we also looked at how Docker facilitates the process of starting and deploying new instances of applications across servers worldwide. This significantly facilitates the movement towards microservices.&lt;/p&gt;

&lt;p&gt;I hope it's been a useful read. Let me know if I left out any other important aspects of this fascinating topic, or if you have any other questions!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>microservices</category>
      <category>monolith</category>
      <category>containers</category>
    </item>
    <item>
      <title>Encapsulation, Polymorphism, and Abstraction in Ruby</title>
      <dc:creator>Vahid Dejwakh</dc:creator>
      <pubDate>Wed, 04 Nov 2020 21:28:52 +0000</pubDate>
      <link>https://dev.to/dej/encapsulation-polymorphism-and-abstraction-in-ruby-41ia</link>
      <guid>https://dev.to/dej/encapsulation-polymorphism-and-abstraction-in-ruby-41ia</guid>
      <description>&lt;p&gt;This article originally appeared on &lt;a href="https://vahid.blog/" rel="noopener noreferrer"&gt;https://vahid.blog/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did you know that Ruby was good for the environment? It is, because it follows strict EPA principles... Encapsulation, Polymorphism, and Abstraction. [Ducks a volley of Tomato objects thrown at him].&lt;/p&gt;

&lt;p&gt;In a &lt;a href="https://www.vahid.blog/post/2020-08-20-understanding-classes-in-javascript/" rel="noopener noreferrer"&gt;previous post&lt;/a&gt;, we discussed the importance of classes in OOP, and developed the mental image of classes as providing more defined jobs and roles to our data. To summarize: classes allow us to build applications that scale well and deal with more complex and customized data structures. They do this by enabling us to &lt;strong&gt;store data&lt;/strong&gt; in specific ways (i.e., attributes) and to &lt;strong&gt;interact with this data&lt;/strong&gt; both internally and from the outside world, also in specific ways (i.e., behaviors, or methods).&lt;/p&gt;

&lt;p&gt;In this article, we'll define and understand all the following terms and concepts: encapsulation, polymorphism, abstraction, method access control, class inheritance, single inheritance, multiple inheritance, duck typing, is-a relationship v.s. has-a relationship, collaborator class and collaborator objects, syntactical sugar, superclass, nil v.s. nothing, dynamically typed v.s. statically typed, interface inheritance, mixin, namespacing, collisions, composition v.s. inheritance, method lookup path, overriding inherited methods, ancestors, and classes v.s. modules.&lt;/p&gt;

&lt;p&gt;In the process, we'll enrich and solidify our understanding of OOP principles, and more fully appreciate the many ways Ruby empowers us to write beautiful, concise, safe, and DRY code. Let's get to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Blocks of OOP
&lt;/h2&gt;

&lt;p&gt;There are three pivotal concepts and building blocks of OOP in Ruby. They are:&lt;br&gt;
1) &lt;strong&gt;Encapsulation&lt;/strong&gt; - Protecting access to data and functionality so that these are unavailable to certain parts of the codebase is how we ensure data is only intentionally accessed and correctly manipulated. The data is thus encapsulated, or shielded.&lt;br&gt;&lt;br&gt; Through the use of class objects, we can create instance variables and instance methods that are encapsulated and thus only accessed by either the object's class or the object itself, but nothing else. Through the use of &lt;em&gt;method access control&lt;/em&gt;, we can even further encapsulate these so that even the object itself does not have access to them. Method access control allows us to qualify instance methods as public, private, or protected, which impacts how accessible these interfaces are to the outside world.&lt;br&gt;&lt;br&gt;Encapsulation also enables &lt;strong&gt;abstraction&lt;/strong&gt;, the third principle of OOP. We could think of abstraction as a subset of encapsulation, but it's such an important concept that many think it deserves to be a standalone principle--and I agree. Encapsulation is also itself meaty and important enough--even &lt;em&gt;without&lt;/em&gt; its role as the father of abstraction--to remain a standalone principle. &lt;br&gt;&lt;br&gt;(&lt;em&gt;Also: I've been wanting to describe something as "the father of abstraction" for a while now, and this was the perfect setup. I wish it was referring to me, but I guess encapsulation is the better man. Alternatively, I could have a kid and name her/him Abstraction. Then, at last, I could claim this glorious title. What? No, she wouldn't mind.&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Polymorphism&lt;/strong&gt; - Literally means "having multiple forms." When objects of different classes have access to the same interface (i.e. method), they are polymorphic. The idea is that the common method reveals and expresses itself in the many different (class) forms or objects it inhabits. &lt;br&gt;&lt;br&gt;The religious studies student in me cannot help but to point out how similar this concept is to polytheism, incarnation, and manifestations of God or the Holy Spirit, where the same divinity takes on many forms, physical or otherwise.&lt;br&gt;&lt;br&gt; Polymorphism can be accomplished through three main ways in Ruby: &lt;em&gt;class inheritance&lt;/em&gt; (i.e. from a &lt;em&gt;superclass&lt;/em&gt;, establishing an "is-a" relationship), &lt;em&gt;interface inheritance&lt;/em&gt; (i.e. from a module &lt;em&gt;mixin&lt;/em&gt;, establishing a "has-a" relationship), and &lt;em&gt;duck typing&lt;/em&gt;. We'll get to each of these later.&lt;br&gt;&lt;br&gt;&lt;em&gt;Sidenote&lt;/em&gt;: some place &lt;strong&gt;inheritance&lt;/strong&gt; as a standalone, fourth principle of OOP, especially in the context of Java. Doing so in Ruby makes less sense, however, because the only practical application of polymorphism &lt;em&gt;as applied to Ruby&lt;/em&gt; is the idea of inheritance. &lt;br&gt;&lt;br&gt;If we extracted and placed inheritance as a standalone principle, polymorphism would just be an empty shell. Plus, we'd also have to do away with that brilliant EPA joke and replace it with some lame E-P-A-&lt;em&gt;I&lt;/em&gt; joke that doesn't even make sense, like:&lt;br&gt;&lt;br&gt; &lt;em&gt;-- "What did the Canadian Rubyist respond when he was asked to incorporate OOP principles?"&lt;/em&gt; &lt;br&gt;&lt;br&gt; &lt;em&gt;-- "API, Eh?"&lt;/em&gt; &lt;br&gt;&lt;br&gt;See? You're welcome.&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Abstraction&lt;/strong&gt; - The ability to simplify complex state and sets of behaviors into one unifying entity makes a programmer's life easier, because all of that complexity is abstracted away and replaced by that umbrella entity (e.g. a class object). This allows us to more easily conceptualize what an object does, how it behaves, and how the outside world should interact with it. &lt;br&gt;&lt;br&gt; For example, for a card game application, we may create a &lt;code&gt;Deck&lt;/code&gt; class that contains, as an attribute, an array of &lt;em&gt;cards&lt;/em&gt;, where cards themselves could be objects of a &lt;code&gt;Card&lt;/code&gt; class. The &lt;code&gt;Card&lt;/code&gt; class may have several attributes, including &lt;code&gt;suit&lt;/code&gt; and &lt;code&gt;face&lt;/code&gt;. Our &lt;code&gt;Deck&lt;/code&gt; class may also contain several behaviors, including &lt;code&gt;deal&lt;/code&gt;, &lt;code&gt;shuffle&lt;/code&gt;, and &lt;code&gt;count&lt;/code&gt; (to return how many cards are left in the stack). This makes our life easier, because we can more abstractly just think of a &lt;code&gt;Deck&lt;/code&gt; object, and not have to worry about all of its methods and attributes, which will remain encapsulated in and "travel with" that &lt;code&gt;Deck&lt;/code&gt; object everywhere it goes.&lt;br&gt;&lt;br&gt;  In this example, both the &lt;code&gt;Card&lt;/code&gt; class and the &lt;code&gt;Array&lt;/code&gt; class are said to be &lt;strong&gt;collaborator classes&lt;/strong&gt; of the &lt;code&gt;Deck&lt;/code&gt; class, since the &lt;code&gt;Deck&lt;/code&gt; class incorporates them as attributes. We can think of collaborator objects as lower levels of abstraction of the owner object whose class incorporates them. We can therefore imagine scenarios of multiple nested collaborator objects, each producing various levels of abstraction.&lt;br&gt;&lt;br&gt; Another example of abstraction is &lt;strong&gt;syntactical sugar&lt;/strong&gt;, which is when a language offers an easier or simpler way of doing something. For example, using &lt;code&gt;[]&lt;/code&gt; to return a specific element at a particular index in an array (or to return a value with that specific key in a hash) is a form of syntactical sugar.&lt;br&gt;&lt;br&gt;Under the hood, calling &lt;code&gt;some_array[4]&lt;/code&gt; is the same thing as calling &lt;code&gt;some_array.[](4)&lt;/code&gt;. The &lt;code&gt;[]&lt;/code&gt; is actually just an instance method that takes an argument, which is the key or index. This &lt;code&gt;[](arg1)&lt;/code&gt; method has been abstracted away and simplified by the smoother &lt;code&gt;[arg1]&lt;/code&gt; method. (&lt;em&gt;Note: both versions can also take an optional second argument and thereby mimic the &lt;code&gt;Array#slice&lt;/code&gt; method, allowing us to capture a range of elements&lt;/em&gt;).&lt;br&gt;&lt;br&gt;  Similarly, doing &lt;code&gt;some_array[3] = 5&lt;/code&gt; is the &lt;em&gt;syntactical sugar&lt;/em&gt; equivalent of &lt;code&gt;some_array.[]=(3,5)&lt;/code&gt;. Under the hood, we are just calling an instance method named &lt;code&gt;[]=&lt;/code&gt; on &lt;code&gt;some_array&lt;/code&gt;, and passing it two arguments: the index number, and the value we want to set the element at that index number to. The &lt;code&gt;[a]=b&lt;/code&gt; form is a more abstracted version of the &lt;code&gt;.[]=(a,b)&lt;/code&gt; form.&lt;br&gt;&lt;br&gt;To conclude, here's a random abstraction joke so that it doesn't feel jealous of the fact that the other two OOP principles got to have jokes:&lt;br&gt;&lt;br&gt; &lt;em&gt;What did the agitated but confused programmer-turned-public defender yell when the prosecutor was making an overly simplistic generalization about the defendant?&lt;/em&gt; &lt;br&gt;&lt;br&gt; &lt;em&gt;-- "Objection, your honor!"&lt;/em&gt; &lt;br&gt;&lt;br&gt; &lt;em&gt;-- "On what grounds?"&lt;/em&gt; &lt;br&gt;&lt;br&gt; &lt;em&gt;-- "Abstraction!"&lt;/em&gt; &lt;br&gt;&lt;br&gt;I mean I could go all day.&lt;/p&gt;

&lt;p&gt;All the three principles of OOP identified above allow our code to be 1) DRY (don't repeat yourself), 2) more maintainable, and also 3) easier to understand and conceptualize.&lt;/p&gt;

&lt;p&gt;Now that we've defined the three main principles of OOP, let's see how classes and modules help us achieve them, and how both of these work together to create the concepts of &lt;em&gt;method lookup path&lt;/em&gt; and &lt;em&gt;ancestors&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here's a diagram that shows the relationships between modules and classes, and some of the most common instances of these that come prepackaged in Ruby. &lt;/p&gt;

&lt;p&gt;Classes are in the light grey rectangles, and modules are in the green clouds.&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%2Fwww.vahid.blog%2Fpost%2F2020-11-04-encapsulation-polymorphism-and-abstraction-in-ruby%2Fclass_hierarchy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.vahid.blog%2Fpost%2F2020-11-04-encapsulation-polymorphism-and-abstraction-in-ruby%2Fclass_hierarchy.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;

[[download diagram as PDF]](https://www.vahid.blog/post/2020-11-04-encapsulation-polymorphism-and-abstraction-in-ruby/class_hierarchy.pdf)

&lt;/center&gt;
&lt;h2&gt;
  
  
  Class Inheritance
&lt;/h2&gt;

&lt;p&gt;Ruby comes with multiple built-in classes, including &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Integer&lt;/code&gt;, &lt;code&gt;Hash&lt;/code&gt;, and &lt;code&gt;Array&lt;/code&gt;. These four classes are probably the most frequently used collaborator classes for any custom classes we might want to create.&lt;/p&gt;

&lt;p&gt;Each class is itself an object (or instance of) the &lt;code&gt;Class&lt;/code&gt; class, which we can think of as the primordial class, sort of like the Biblical Adam and Eve of all classes. &lt;/p&gt;

&lt;p&gt;What is &lt;strong&gt;class inheritance&lt;/strong&gt;? Every class inherits methods and attributes from another class, which we refer to as the class's &lt;code&gt;superclass&lt;/code&gt;. Calling the class method &lt;code&gt;superclass&lt;/code&gt; on any class will return that class's superclass. For example: &lt;code&gt;puts Integer.superclass&lt;/code&gt; will output &lt;code&gt;Numeric&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Every class has one (&lt;em&gt;and only one&lt;/em&gt;) superclass. This is called &lt;strong&gt;single inheritance&lt;/strong&gt; because a class can only have a single parent. When we create a custom class without explicitly defining a superclass to inherit from, our custom class implicitly inherits from the &lt;code&gt;Object&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;In the diagram above, we see that the superclass of &lt;code&gt;Numeric&lt;/code&gt; is &lt;code&gt;Object&lt;/code&gt;, and the superclass of &lt;code&gt;Object&lt;/code&gt; is &lt;code&gt;BasicObject&lt;/code&gt;. What's the superclass of &lt;code&gt;BasicObject&lt;/code&gt;? It's &lt;code&gt;nil&lt;/code&gt;. &lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;em&gt;Sidenote 1:&lt;/em&gt; the difference between &lt;code&gt;nil&lt;/code&gt; and nothing
&lt;/h4&gt;

&lt;p&gt;Nil is not the same thing as &lt;em&gt;nothing&lt;/em&gt;, however. Although &lt;code&gt;nil&lt;/code&gt; is not a class, it &lt;em&gt;is&lt;/em&gt; an object, an object of the class &lt;code&gt;NilClass&lt;/code&gt;, whose superclass is &lt;code&gt;Object&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Why is this distinction important? After all, if we have an array, &lt;code&gt;some_array&lt;/code&gt;, containing 5 elements, and we call &lt;code&gt;some_array[10]&lt;/code&gt;, we'd get &lt;code&gt;nil&lt;/code&gt; back. Doesn't that mean that &lt;code&gt;nil&lt;/code&gt; is the same thing as &lt;em&gt;nothing&lt;/em&gt;? &lt;/p&gt;

&lt;p&gt;It appears that way, but it's not. The reason we get &lt;code&gt;nil&lt;/code&gt; back is because the &lt;code&gt;[]&lt;/code&gt; instance method, as defined in the &lt;code&gt;Array&lt;/code&gt; class definition, is explicitly defined to return the &lt;code&gt;nil&lt;/code&gt; object if there's no key that matches the argument (i.e. the index) passed in to the &lt;code&gt;[]&lt;/code&gt; method. &lt;/p&gt;

&lt;p&gt;If we instead use the &lt;code&gt;fetch&lt;/code&gt; instance method, however, which contains no such safety measure, we'd get an error back if we try to search for a key that doesn't exist. So when there is nothing, we get an error. If there is something, even if it's &lt;code&gt;nil&lt;/code&gt;, we get that something back (i.e. we'd get &lt;code&gt;nil&lt;/code&gt; back). This means that &lt;code&gt;nil&lt;/code&gt; is not the same thing as &lt;em&gt;nothing&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;em&gt;Sidenote 2:&lt;/em&gt; Ruby has no Bool(ean)
&lt;/h4&gt;

&lt;p&gt;Note, too, that Ruby doesn't have a "Boolean" class, which is unlike most other OOP languages. Ruby &lt;em&gt;does&lt;/em&gt; have separate &lt;code&gt;TrueClass&lt;/code&gt; and &lt;code&gt;FalseClass&lt;/code&gt; classes, but there's no overarching "Boolean" class from which both might inherit--instead, those two classes each directly inherit from &lt;code&gt;Object&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The reason for this has to do with the fact that Ruby is &lt;em&gt;dynamically&lt;/em&gt; typed (as opposed to &lt;em&gt;statically&lt;/em&gt; typed like C++ and Java). This means that in Ruby, we don't need to explicitly define what the class of a variable is. We instead dynamically (and implicitly) assign it a class, and can easily reassign it to another class (for better or for worse). A variable can therefore easily be assigned to &lt;code&gt;true&lt;/code&gt;, an object of the &lt;code&gt;TrueClass&lt;/code&gt; class, and then reassigned to &lt;code&gt;false&lt;/code&gt;, an object of the &lt;code&gt;FalseClass&lt;/code&gt; class. &lt;/p&gt;

&lt;p&gt;Finally, as this &lt;a href="https://www.rubytapas.com/2019/01/08/boolean/" rel="noopener noreferrer"&gt;more in-depth answer to this question&lt;/a&gt; argues, there just aren't enough shared behaviors between the two classes to warrant creating a common superclass. Yukihiro Matsumoto, the creator of Ruby (and affectionately known as &lt;em&gt;Matz&lt;/em&gt; by Rubyists), &lt;a href="https://bugs.ruby-lang.org/issues/12515" rel="noopener noreferrer"&gt;has explained&lt;/a&gt; why he rejected calls to create a Boolean superclass.&lt;/p&gt;
&lt;h4&gt;
  
  
  Duck typing
&lt;/h4&gt;

&lt;p&gt;The previous discussion is a perfect segue to &lt;strong&gt;duck typing&lt;/strong&gt;. In Ruby, we are less concerned with what the &lt;em&gt;class&lt;/em&gt; of an object is, and more with its &lt;em&gt;capabilities&lt;/em&gt;, i.e. what instance methods we can call on it. If objects A and B are of different classes but they can both respond to a &lt;em&gt;quack&lt;/em&gt; instance method, for example, then we can treat both as &lt;em&gt;ducks&lt;/em&gt; (hence the name). If it quacks like a duck,...&lt;/p&gt;

&lt;p&gt;To accomplish duck typing (i.e. &lt;em&gt;not&lt;/em&gt; class inheritance), we can just merely explicitly define the same method in each class definition. Then, for example, we can call that method on any object of any of those classes, and we will get an acceptable, proper return. Duck typing is another, &lt;em&gt;more explicit&lt;/em&gt; way to achieve polymorphism.&lt;/p&gt;



&lt;p&gt;Is class inheritance the only way to inherit functionality? No--in Ruby, modules also allow this through &lt;em&gt;interface inheritance&lt;/em&gt;. Let's dig into them next.&lt;/p&gt;
&lt;h2&gt;
  
  
  Modules and Interface Inheritance
&lt;/h2&gt;

&lt;p&gt;All modules are objects of the &lt;code&gt;Module&lt;/code&gt; class, which is itself an object of the &lt;code&gt;Class&lt;/code&gt; class. Modules play two main roles in Ruby's implementation of OOP principles:&lt;br&gt;
1) &lt;strong&gt;Interface inheritance&lt;/strong&gt; - We can include the functionality of any module into any class by using the keyword &lt;code&gt;include&lt;/code&gt;, followed by the module's name. Also known as a &lt;strong&gt;mixin&lt;/strong&gt; (an abbreviation of "mixed in"), this allows all objects of that class to have access to all the instance methods defined in the module.&lt;br&gt;&lt;br&gt;As the diagram shows, several native Ruby classes mix in either the &lt;code&gt;Comparable&lt;/code&gt; or the &lt;code&gt;Enumerable&lt;/code&gt; module. A common naming practice when creating a module that is used as a mixin is to name it with something that ends with "-able"--this makes it more easily identifiable and distinguishable from the other main type of module, used instead for namespacing.&lt;br&gt;&lt;br&gt;Because there's no limit to how many modules you can include in a class, modules is how Ruby enables &lt;strong&gt;multiple inheritance&lt;/strong&gt;. If a class needs to inherit two (or more) distinctly different sets of behaviors, you can't use class inheritance to do this, but you can use a mixin instead.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Namespacing&lt;/strong&gt; - Modules can also double up as &lt;strong&gt;containers&lt;/strong&gt; for any number of constants, classes, and/or isolated methods that don't really belong to any specific class. A great example of modules as a namespace is the &lt;code&gt;Math&lt;/code&gt; module, which contains mathematical constants like &lt;code&gt;Math::PI&lt;/code&gt; and methods like &lt;code&gt;Math.cos&lt;/code&gt; (also accessible with &lt;code&gt;Math::cos&lt;/code&gt;, though the former is the preferred way for calling module methods). This can be particularly useful when creating libraries/gems, or even when different team members are working on different features of a common application. &lt;br&gt;&lt;br&gt;Namespacing is a practical way to not only organize related behaviors together, but to also prevent &lt;strong&gt;collisions&lt;/strong&gt;. There's a likely possibility that more than one member of a large team (or that more than one gem or library) might name a custom class the same way, which would cause one class definition to collide with and override the other when they merge their code into the same branch, or when they combine those gems or libraries together.&lt;br&gt;&lt;br&gt; Instead, they can place their class definition inside a module which could be named after their particular feature or gem, for example. That way, they can more explicitly access the class inside the module that they created, which would be distinct and encapsulated away from the same class inside another module.&lt;br&gt;&lt;br&gt;For example, let's say Amanda and George both had to create a &lt;code&gt;Student&lt;/code&gt; class for the feature they were building. However, Amanda's implementation focused on the financial side of the application and had to track how much tuition the student had paid so far, and how much they still owed, etc. George, on the other hand, was working on an academics-focused feature and using the &lt;code&gt;Student&lt;/code&gt; class to track all the classes each student had taken, their grade for each class, cumulative GPA, etc. &lt;br&gt;&lt;br&gt;Amanda can use namespacing and create a module called &lt;code&gt;Finances&lt;/code&gt;, then define her &lt;code&gt;Student&lt;/code&gt; class inside there. Anytime she wanted to instantiate a new student for her purposes, she could call &lt;code&gt;Finances::Student.new&lt;/code&gt; and pass in any necessary arguments. &lt;br&gt;&lt;br&gt;Similarly, George could create an &lt;code&gt;Academics&lt;/code&gt; module, and define his &lt;code&gt;Student&lt;/code&gt; class there. He would instantiate a new student by calling &lt;code&gt;Academics::Student.new&lt;/code&gt;, along with any necessary arguments.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;em&gt;Sidenote 3:&lt;/em&gt; Composition v.s. Inheritance
&lt;/h4&gt;

&lt;p&gt;In some OOP languages, the terms "inheritance" and "inherit" are exclusively used in the context of (and more narrowly used to refer to) when a class receives interfaces from a superclass (i.e., what we've had to qualify as &lt;em&gt;class&lt;/em&gt; inheritance because of our broader/looser use of the term "inheritance"). While we described a mixin as an example of "interface &lt;em&gt;inheritance&lt;/em&gt;," they would instead call it an example of a &lt;strong&gt;composition&lt;/strong&gt;. &lt;br&gt;&lt;br&gt;This is worth noting here only because &lt;a href="https://en.wikipedia.org/wiki/Composition_over_inheritance" rel="noopener noreferrer"&gt;Composition over Inheritance&lt;/a&gt; is a specific OOP design pattern that argues that favoring "has-a" relationships (i.e. through compositions, or mixins) ensures our code is more flexible and reusable than using "is-a" relationships (i.e. through class inheritance). This is why the Go language does not even allow class inheritance, and only uses compositions.&lt;br&gt;&lt;br&gt; For our purposes, we can think of "composition" as just another term for a mixin, and appreciate that to some people, we may sound redundant when we say "class inheritance."&lt;/p&gt;
&lt;h2&gt;
  
  
  Method Lookup Path
&lt;/h2&gt;

&lt;p&gt;Now that we've covered both class inheritance and module mixins, we can conceptualize the &lt;strong&gt;method lookup path&lt;/strong&gt;. Whenever an instance method is called on an object, Ruby looks for that method definition in that object's class definition. If it doesn't find it there, it searches for it in any and all modules included in the class, from bottom up. Finally, if it doesn't find the method in the modules included in the class, it goes up the class inheritance chain and looks for it in the class's superclass.&lt;br&gt;&lt;br&gt; It keeps going &lt;em&gt;vertically&lt;/em&gt; up the class inheritance tree, then &lt;em&gt;horizontally&lt;/em&gt; through all mixins of that class, then up again, etc, until it hits the &lt;code&gt;BasicObject&lt;/code&gt; class, which is the last stop.&lt;/p&gt;

&lt;p&gt;Let's look at an example. If we have an array, &lt;code&gt;some_array = [3,6,9]&lt;/code&gt;, and we then call &lt;code&gt;some_array.max&lt;/code&gt;, Ruby will search for the definition of the &lt;code&gt;max&lt;/code&gt; instance method first in the &lt;code&gt;Array&lt;/code&gt; class definition, since &lt;code&gt;some_array&lt;/code&gt; is of the &lt;code&gt;Array&lt;/code&gt; class. Notice from the diagram that &lt;code&gt;Array&lt;/code&gt; includes the &lt;code&gt;Enumerable&lt;/code&gt; module, which means that's where Ruby will search next. If it didn't find it there, it would then go up to the superclass of &lt;code&gt;Array&lt;/code&gt;, which is &lt;code&gt;Object&lt;/code&gt;, then to &lt;code&gt;Kernel&lt;/code&gt;, which is a module mixed in to &lt;code&gt;Object&lt;/code&gt;, and finally up to &lt;code&gt;BasicObject&lt;/code&gt;. Again, the superclass of &lt;code&gt;BasicObject&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt;, so that's always going to be the tail-end of our lookup path.&lt;/p&gt;

&lt;p&gt;The method lookup path helps to explain the concept of &lt;strong&gt;overriding inherited methods&lt;/strong&gt;. Because Ruby looks for the method in the class itself first, we can "override" a method that a class inherited from a superclass or module by explicitly defining it in the class. Ruby would therefore use that lower-level version of that method and never get to the version of the method that's defined further up the method lookup path.&lt;/p&gt;

&lt;p&gt;In order to figure out all the modules a class includes, the class method &lt;code&gt;included_modules&lt;/code&gt; is useful. This class method travels up the method lookup path, and returns all the modules it encounters along the way, as an array. &lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;Hash.included_modules&lt;/code&gt; would return an array of two elements, &lt;code&gt;Enumerable&lt;/code&gt; and &lt;code&gt;Kernel&lt;/code&gt;, which are the two modules that &lt;code&gt;Hash&lt;/code&gt; objects inherit from, since &lt;code&gt;Hash&lt;/code&gt; directly includes &lt;code&gt;Enumerable&lt;/code&gt;, and &lt;code&gt;Object&lt;/code&gt; includes &lt;code&gt;Kernel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even more useful is the &lt;code&gt;ancestors&lt;/code&gt; class method, which returns the entire method lookup path itself, also as an array. For example, calling &lt;code&gt;Integer.ancestors&lt;/code&gt; returns: &lt;code&gt;[Integer, Numeric, Comparable, Object, Kernel, BasicObject]&lt;/code&gt;. Note that &lt;code&gt;ancestors&lt;/code&gt; is a &lt;em&gt;class method&lt;/em&gt;, so we couldn't call it directly on an object. We'd have to first call the &lt;code&gt;class&lt;/code&gt; instance method to return the object's class, and then call &lt;code&gt;ancestors&lt;/code&gt; on &lt;em&gt;that&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;For example:&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="n"&gt;some_num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;some_num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ancestors&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion &amp;amp; putting it all together
&lt;/h2&gt;

&lt;p&gt;Wow. You've made it this far--kuddos to you! &lt;/p&gt;

&lt;p&gt;As a reward, here's a useful table to recap the three main OOP principles, and how classes and modules help us implement each one.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;OOP Principle&lt;/th&gt;
&lt;th&gt;Classes&lt;/th&gt;
&lt;th&gt;Modules&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Encapsulation&lt;/td&gt;
&lt;td&gt;* Classes shield class variables and class methods &lt;br&gt;* Each object of a class shields its own unique instance variables (i.e. state) &lt;br&gt; * Method access control shields object-specific data and behavior even further by allowing us to qualify certain instance methods as private or protected&lt;/td&gt;
&lt;td&gt;Namespacing allows modules to shield variables, constants, methods, and even classes so that they don't collide with other similarly named objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polymorphism&lt;/td&gt;
&lt;td&gt;Class inheritance and duck typing&lt;/td&gt;
&lt;td&gt;Interface inheritance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Abstraction&lt;/td&gt;
&lt;td&gt;Instantiating objects from a class allows each object to abstract away its internal complexity through an "is-a" relationship&lt;/td&gt;
&lt;td&gt;Including a module through a mixin abstracts away some behavior complexity through a "has-a" relationship&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When should you use &lt;strong&gt;classes&lt;/strong&gt;, and when should you use &lt;strong&gt;modules&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Here's a few guidelines to keep in mind when deciding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you need to create objects from the same mold, you &lt;em&gt;have to&lt;/em&gt; use a class. Modules cannot instantiate objects.&lt;/li&gt;
&lt;li&gt;If data type X is a more specific &lt;em&gt;type of&lt;/em&gt; class Y, meaning that X has an "is-a" relationship with Y, then it makes sense to use a class to define X, and have it inherit from its superclass, Y&lt;/li&gt;
&lt;li&gt;If Y and Z are unrelated classes that both need to inherit the same functionality of X, meaning Y and Z each have a "has-a" relationship with X, then it makes sense to use a module to define X, and have both Y and Z include X through a mixin.&lt;/li&gt;
&lt;li&gt;If you want a way to compartmentalize a set of behaviors or classes, use a module.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Special thanks to the &lt;a href="https://www.launchschool.com" rel="noopener noreferrer"&gt;Launch School&lt;/a&gt; curriculum, TAs, and students who all helped me solidify these concepts.&lt;/p&gt;

&lt;p&gt;Questions? Confused? Leave your thoughts below. &lt;/p&gt;

</description>
      <category>ruby</category>
      <category>oop</category>
      <category>inheritance</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Understanding Classes in JavaScript</title>
      <dc:creator>Vahid Dejwakh</dc:creator>
      <pubDate>Thu, 17 Sep 2020 12:15:44 +0000</pubDate>
      <link>https://dev.to/dej/understanding-classes-in-javascript-49g3</link>
      <guid>https://dev.to/dej/understanding-classes-in-javascript-49g3</guid>
      <description>&lt;p&gt;This post originally appeared on &lt;a href="https://vahid.blog"&gt;https://vahid.blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Integers, floats, strings, arrays, objects, functions, loops, scope? Piece of cake. Classes? Not so easy.&lt;/p&gt;

&lt;p&gt;Understanding what &lt;strong&gt;classes&lt;/strong&gt; are, how they work, and how to incorporate them into your code is critical to developing any working enterprise application. Even more importantly, however, developing a better mental model and appreciation for classes will transform you from a mere programming hobbyist to a software craftsman demigod.&lt;/p&gt;

&lt;p&gt;Let's get to it.&lt;/p&gt;

&lt;p&gt;Every data structure, including all the ones listed above, is a class. Programming languages each come with your basic and fundamental class types, like numbers, strings, arrays, functions, and--for most modern languages at least--objects. Beyond these fundamental types, however, you can use classes to create your own customized data type. You can make this customized data type store whatever bits of information you need, in whatever format you want.&lt;/p&gt;

&lt;p&gt;"Why would you I want to create a new class?" you grumble under your breath. "All I need are the fundamental data types," you explain further: "I can already store anything I could possibly want in them."&lt;/p&gt;

&lt;p&gt;The reason, my wary but intrepid friend, is twofold: scalability and complexity. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First, there's the issue of &lt;strong&gt;scalability&lt;/strong&gt;. As your application grows in size, you will have thousands, maybe billions, of variables, containing multiple data types per user, per feature, per environment (development vs testing vs production), per date, and even also per software release version.&lt;br&gt;&lt;br&gt;Classes are going to serve as neat, clean, and well labeled shelves to put all your various related data into a much more organized, retrievable, and maintainable structure. Without this structure, your application might work as an MVP or prototype but would not be able to scale.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then there's &lt;strong&gt;complexity&lt;/strong&gt;. The world of data structures is so deep and profound, and you've only scratched the surface. To create linked lists, hash tables, components in React, binary search trees, and so many more interesting and complex data structures, we need classes. Without classes, we would not be able to have a working mental model of what those data structures do, nor how their instantiations (i.e. variables of a particular class) behave &lt;em&gt;in the wild&lt;/em&gt;. &lt;br&gt;&lt;br&gt; A class allows you to wrap your mind around a specific data type so that you're able to not only apply that data type to its intended use case, but to also be able to troubleshoot when an instantiation of that class is misbehaving. Think of a class as a chunk of several subchunks of data types (if that analogy didn't make sense, &lt;a href="https://vahid.blog/post/2020-08-13-learning-how-to-learn/#2-chunking"&gt;read this&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, why are classes important in object oriented programming (OOP)? They bring scalability and complexity to our application. &lt;/p&gt;

&lt;p&gt;Classes provide identity and function to data. In other words, classes allow our data to have well defined jobs. To have a functioning society, everybody needs to have a role to play--right? The better defined and specialized that role is, the more valuable each member becomes. &lt;/p&gt;

&lt;p&gt;The same applies to our data in our application. Indeed, the fact that you need more, better, or more defined classes is usually a sign that your application is growing and becoming more competent and specialized.&lt;/p&gt;

</description>
      <category>classes</category>
      <category>datastructure</category>
      <category>oop</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Syntax Differences Between Ruby and Javascript</title>
      <dc:creator>Vahid Dejwakh</dc:creator>
      <pubDate>Tue, 01 Sep 2020 21:44:42 +0000</pubDate>
      <link>https://dev.to/dej/syntax-differences-between-ruby-and-javascript-1adl</link>
      <guid>https://dev.to/dej/syntax-differences-between-ruby-and-javascript-1adl</guid>
      <description>&lt;p&gt;This article originally appeared on &lt;a href="https://vahid.blog"&gt;https://vahid.blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've been working with Javascript for a while now, and have gotten fairly comfortable with its syntax. &lt;/p&gt;

&lt;p&gt;I'm now also using Ruby again, which has a slightly different flavor. &lt;/p&gt;

&lt;p&gt;Here are some of the main syntactical differences between the two languages, in table format.&lt;/p&gt;



&lt;h2&gt;
  
  
  1. Basics
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Javascript&lt;/th&gt;
&lt;th&gt;Ruby&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Naming convention for variables, functions, and methods&lt;/td&gt;
&lt;td&gt;camelCase&lt;/td&gt;
&lt;td&gt;snake_case&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Naming convention for classes&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Declaring variables&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;let&lt;/code&gt; someArray &lt;code&gt;= [&lt;/code&gt;1,2&lt;code&gt;];&lt;/code&gt; &lt;br&gt;&lt;br&gt; Although &lt;code&gt;var&lt;/code&gt; was exclusively used in older codebases, &lt;code&gt;let&lt;/code&gt; is now more encouraged because &lt;code&gt;let&lt;/code&gt; is block scoped while &lt;code&gt;var&lt;/code&gt; is function scoped and can cause unintended consequences&lt;/td&gt;
&lt;td&gt;some_array &lt;code&gt;= [&lt;/code&gt;1,2&lt;code&gt;]&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Declaring constants&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;const&lt;/code&gt; SOMECONSTANT &lt;code&gt;=&lt;/code&gt;3.14&lt;code&gt;;&lt;/code&gt;&lt;br&gt;&lt;br&gt;Reassigning something else to the constant will throw an error&lt;/td&gt;
&lt;td&gt;SOME_CONSTANT &lt;code&gt;=&lt;/code&gt; 3.14&lt;br&gt;&lt;br&gt;Ruby will throw a warning when attempting to reassign something else to the constant, but will let you do it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Declaring global variables&lt;/td&gt;
&lt;td&gt;Declare the variable with &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt; in the global context. &lt;br&gt;&lt;br&gt;However, if a variable with the same name is declared in a local scope, the local variable will be usable in that scope but not the global variable&lt;/td&gt;
&lt;td&gt;You can declare a global variable anywhere by using a &lt;code&gt;$&lt;/code&gt; just in front of the variable name&lt;br&gt;&lt;br&gt; (e.g. &lt;code&gt;$&lt;/code&gt;this_is_a_global_variable &lt;code&gt;=&lt;/code&gt; 2100 )&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comments&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;//&lt;/code&gt;this is a single-line comment in JS&lt;br&gt;&lt;br&gt;&lt;code&gt;/*&lt;/code&gt;&lt;br&gt; This is&lt;br&gt;a multi-line&lt;br&gt;comment&lt;br&gt;in JS&lt;br&gt; &lt;code&gt;*/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;#&lt;/code&gt;this is a single-line comment in Ruby&lt;br&gt;&lt;br&gt;&lt;code&gt;=begin&lt;/code&gt;&lt;br&gt;This is&lt;br&gt;a multi-line&lt;br&gt;comment&lt;br&gt;in Ruby&lt;br&gt;&lt;code&gt;=end&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Print to console (automatically adding new line)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;console.log(&lt;/code&gt;'hello world'&lt;code&gt;);&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;puts&lt;/code&gt; 'hello world'&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Print to console (without new line)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;process.stdout.write(&lt;/code&gt;'hello'&lt;code&gt;);&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;print&lt;/code&gt; 'hello'&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conditional Statements&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;if (&lt;/code&gt;someCondition&lt;code&gt;) {&lt;/code&gt; &lt;br&gt;   &lt;code&gt;//&lt;/code&gt;do this&lt;br&gt;  &lt;code&gt;//&lt;/code&gt;and this &lt;br&gt; &lt;code&gt;} else if (&lt;/code&gt;someOtherCondition&lt;code&gt;) {&lt;/code&gt;&lt;br&gt;   &lt;code&gt;//&lt;/code&gt;do this instead&lt;br&gt;&lt;code&gt;} else {&lt;/code&gt;&lt;br&gt;   &lt;code&gt;//&lt;/code&gt;otherwise do this&lt;br&gt;&lt;code&gt;}&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;if&lt;/code&gt; some_condition &lt;br&gt;   &lt;code&gt;#&lt;/code&gt;do this &lt;br&gt;   &lt;code&gt;#&lt;/code&gt;and this &lt;br&gt;&lt;code&gt;elsif&lt;/code&gt; some_other_condition &lt;br&gt;   &lt;code&gt;#&lt;/code&gt;do this instead &lt;br&gt;&lt;code&gt;else&lt;/code&gt;&lt;br&gt;   &lt;code&gt;#&lt;/code&gt;otherwise do this&lt;br&gt;&lt;code&gt;end&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;one-line conditional statement&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;if (&lt;/code&gt;condition&lt;code&gt;)&lt;/code&gt; doThis&lt;code&gt;;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;do_this &lt;code&gt;if&lt;/code&gt; condition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ternary conditional expression&lt;/td&gt;
&lt;td&gt;condition &lt;code&gt;?&lt;/code&gt; doThisIfTrue &lt;code&gt;:&lt;/code&gt; doThisIfFalse&lt;code&gt;;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;condition &lt;code&gt;?&lt;/code&gt; do_this_if_true &lt;code&gt;:&lt;/code&gt; do_this_if_false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Switch / case statement&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;switch(&lt;/code&gt;expression&lt;code&gt;) {&lt;/code&gt; &lt;br&gt;   &lt;code&gt;case&lt;/code&gt; x: &lt;br&gt;      &lt;code&gt;//&lt;/code&gt; code block&lt;br&gt;     &lt;code&gt;break;&lt;/code&gt; &lt;br&gt;    &lt;code&gt;case&lt;/code&gt; y:&lt;br&gt;     // code block&lt;br&gt;     &lt;code&gt;break;&lt;/code&gt;&lt;br&gt;   &lt;code&gt;default:&lt;/code&gt; &lt;br&gt;     &lt;code&gt;//&lt;/code&gt; code block&lt;br&gt;&lt;code&gt;}&lt;/code&gt; &lt;br&gt;&lt;br&gt; If you do not &lt;code&gt;break&lt;/code&gt;, JS will execute every line after that case too&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;case&lt;/code&gt; expression&lt;br&gt;   &lt;code&gt;when&lt;/code&gt; x &lt;br&gt;    &lt;code&gt;#&lt;/code&gt;code block &lt;br&gt;   &lt;code&gt;when&lt;/code&gt; y &lt;br&gt;    &lt;code&gt;#&lt;/code&gt;code block &lt;br&gt;   &lt;code&gt;else&lt;/code&gt;&lt;br&gt;    &lt;code&gt;#&lt;/code&gt;code block &lt;br&gt;&lt;code&gt;end&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Define a function / method&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;function&lt;/code&gt; someFunction&lt;code&gt;(&lt;/code&gt;param1, param2&lt;code&gt;){&lt;/code&gt;&lt;br&gt;  &lt;code&gt;//&lt;/code&gt;do stuff&lt;br&gt;  &lt;code&gt;return&lt;/code&gt; something;&lt;br&gt;&lt;code&gt;}&lt;/code&gt;&lt;br&gt;&lt;br&gt;If the &lt;code&gt;return&lt;/code&gt; keyword is never used, the function will return &lt;code&gt;undefined&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;def&lt;/code&gt; some_method&lt;code&gt;(&lt;/code&gt;param1, param2&lt;code&gt;)&lt;/code&gt;&lt;br&gt;  &lt;code&gt;#&lt;/code&gt;do stuff&lt;br&gt;  &lt;code&gt;return&lt;/code&gt; something&lt;br&gt;&lt;code&gt;end&lt;/code&gt;&lt;br&gt;&lt;br&gt;If the &lt;code&gt;return&lt;/code&gt; keyword is never used, the method will return whatever is calculated on the last line before the &lt;code&gt;end&lt;/code&gt; statement.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keyword to refer to the current particular instantiated object&lt;/td&gt;
&lt;td&gt;&lt;code&gt;this&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;self&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error handling&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;try {&lt;/code&gt; &lt;br&gt;   &lt;code&gt;//&lt;/code&gt; do something risky &lt;br&gt; &lt;code&gt;} catch(err) {&lt;/code&gt; &lt;br&gt;  &lt;code&gt;//&lt;/code&gt; handle error here &lt;br&gt; &lt;code&gt;}&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;begin&lt;/code&gt; &lt;br&gt;    &lt;code&gt;#&lt;/code&gt; do something risky &lt;br&gt; &lt;code&gt;rescue&lt;/code&gt; &lt;br&gt;   &lt;code&gt;#&lt;/code&gt; handle error here &lt;br&gt; &lt;code&gt;end&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Arrays &amp;amp; Strings
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Javascript&lt;/th&gt;
&lt;th&gt;Ruby&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Map / Collect method &lt;br&gt;(Returning a new array of tweaked elements from an original array)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;const&lt;/code&gt; newArray &lt;code&gt;=&lt;/code&gt; someArray&lt;code&gt;.map(&lt;/code&gt;el&lt;code&gt;=&amp;gt;&lt;/code&gt; el * 2&lt;code&gt;)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;new_array &lt;code&gt;=&lt;/code&gt; some_array`.map {&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iterate through an array's elements in one line and no need for index #&lt;/td&gt;
&lt;td&gt;someArray.forEach(el =&amp;gt; console.log(el));&lt;/td&gt;
&lt;td&gt;some_array.each {&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iterate through an array's elements to perform a block requiring index #&lt;/td&gt;
&lt;td&gt;for(let i=0; i &amp;lt; someArr.length; i++){&lt;br&gt;  console.log(i, someArr[i]);&lt;br&gt;   // rest of block&lt;br&gt;}&lt;/td&gt;
&lt;td&gt;some_arr.each_index do&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete an element at index i of an array&lt;/td&gt;
&lt;td&gt;someArray.splice(i,length); &lt;br&gt;&lt;br&gt; Where i=index # to start deleting, and &lt;br&gt;length = # of elements to delete&lt;/td&gt;
&lt;td&gt;some_array.delete_at(i)&lt;br&gt;&lt;br&gt; To delete all elements of a particular value (e.g. 'cat') regardless of index number, use:&lt;br&gt; some_array.delete('cat')&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Return the unique values of an array&lt;/td&gt;
&lt;td&gt;const uniqueArray = [...new Set(someArray)];&lt;/td&gt;
&lt;td&gt;unique_array = some_array.uniq &lt;br&gt;&lt;br&gt; To mutate the &lt;em&gt;original&lt;/em&gt; array and retain only its unique values, use:&lt;br&gt; someArray.uniq!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Filter an array&lt;/td&gt;
&lt;td&gt;const filteredArray = someArray.filter(el =&amp;gt; el &amp;gt; 5);&lt;br&gt;&lt;br&gt;E.g. Returns all elements in someArray greater than 5&lt;/td&gt;
&lt;td&gt;filtered_array = some_array.select {&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check if an element is in an array&lt;/td&gt;
&lt;td&gt;someArray.includes(5); &lt;br&gt;&lt;br&gt; E.g. Returns true if someArray has an element with a value of 5&lt;/td&gt;
&lt;td&gt;some_array.include?(5) &lt;br&gt;&lt;br&gt; E.g. Returns true if some_array has an element with a value of 5 &lt;br&gt;&lt;br&gt;For methods that return a boolean, a Ruby convention is to name them with a ? at the end&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;String Concatenation&lt;/td&gt;
&lt;td&gt;someString = 'Hi,' + someName;&lt;br&gt;&lt;br&gt; If the left side of the {% raw %}&lt;code&gt;+&lt;/code&gt; is a string, then JS will coerce anything that appears on the right side into a string too, even if it's a number or another data type&lt;/td&gt;
&lt;td&gt;some_string = 'Hi,' + some_name &lt;br&gt;&lt;br&gt; Ruby will throw an error if you attempt to concatenate a string with a non-string. You must convert it to a string first (i.e. &lt;code&gt;.to_s&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Convert a number to a string&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;let&lt;/code&gt; varString &lt;code&gt;=&lt;/code&gt; someNum&lt;code&gt;.toString();&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;var_string &lt;code&gt;=&lt;/code&gt; some_num&lt;code&gt;.to_s&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Convert a string to an integer&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;let&lt;/code&gt; varNum &lt;code&gt;= Number(&lt;/code&gt;someString&lt;code&gt;);&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;var_num &lt;code&gt;=&lt;/code&gt; some_string&lt;code&gt;.to_i&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Convert a string to a float&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;let&lt;/code&gt; varNum &lt;code&gt;= parseFloat(&lt;/code&gt;someString&lt;code&gt;);&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;var_num &lt;code&gt;=&lt;/code&gt; some_string&lt;code&gt;.to_f&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Objects / Hashes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Javascript&lt;/th&gt;
&lt;th&gt;Ruby&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Key-value pair data type is called&lt;/td&gt;
&lt;td&gt;an object&lt;/td&gt;
&lt;td&gt;a hash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;object/hash creation + assignment &lt;br&gt;&lt;br&gt;(Literal notation)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;const&lt;/code&gt; someObject &lt;code&gt;= {&lt;/code&gt;key1&lt;code&gt;:&lt;/code&gt; value1&lt;code&gt;,&lt;/code&gt; key2&lt;code&gt;:&lt;/code&gt; value2&lt;code&gt;};&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;the older, symbol &amp;amp; hash-rocket method:&lt;br&gt;some_hash &lt;code&gt;= {:&lt;/code&gt;key1 &lt;code&gt;=&amp;gt;&lt;/code&gt; value1&lt;code&gt;, :&lt;/code&gt;key2 &lt;code&gt;=&amp;gt;&lt;/code&gt; value2&lt;code&gt;}&lt;/code&gt;&lt;br&gt;&lt;br&gt; or the newer, cleaner method: &lt;br&gt;some_hash &lt;code&gt;= {&lt;/code&gt;key1&lt;code&gt;:&lt;/code&gt; value1&lt;code&gt;,&lt;/code&gt; key2&lt;code&gt;:&lt;/code&gt; value2&lt;code&gt;}&lt;/code&gt;&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object/hash creation &lt;br&gt;&lt;br&gt;(class instantiation notation)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;const&lt;/code&gt; someObject &lt;code&gt;= new Object;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;some_hash &lt;code&gt;= Hash.new&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add key/value pair to an existing object/hash&lt;/td&gt;
&lt;td&gt;someExistingObject[key3] &lt;code&gt;=&lt;/code&gt; value3&lt;code&gt;;&lt;/code&gt; &lt;br&gt;&lt;br&gt;or&lt;br&gt;&lt;br&gt; someExistingObject.key3 &lt;code&gt;=&lt;/code&gt; value3&lt;code&gt;;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;some_existing_object[&lt;code&gt;:&lt;/code&gt;key3] &lt;code&gt;=&lt;/code&gt; value3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iterate through an object/hash in one line&lt;/td&gt;
&lt;td&gt;for(let key in someObject) { console.log(key,someObject[key])};&lt;/td&gt;
&lt;td&gt;some_hash.each {&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;convert an object/hash to an array of sub-arrays of [key,value]&lt;/td&gt;
&lt;td&gt;const someArray = &lt;code&gt;Object.entries(&lt;/code&gt;someObject&lt;code&gt;);&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;some_array = some_hash.to_a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete a key/value pair&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;delete&lt;/code&gt; someObject[someKey];&lt;/td&gt;
&lt;td&gt;some_hash.delete(some_key)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check if an object/hash has a key&lt;/td&gt;
&lt;td&gt;someObject.hasOwnProperty(someKey)&lt;/td&gt;
&lt;td&gt;some_hash.has_key?(some_key)&lt;br&gt;&lt;br&gt;&lt;center&gt;- or -&lt;/center&gt;
&lt;br&gt;&lt;br&gt;the &lt;code&gt;fetch&lt;/code&gt; method allows you to get the value at the key or specify an alternative return value if the key doesn't exist:&lt;br&gt;&lt;br&gt; some_hash.fetch(some_key, "error message")&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>syntax</category>
      <category>ruby</category>
      <category>javascript</category>
      <category>languages</category>
    </item>
    <item>
      <title>What's the difference between a framework and a library?</title>
      <dc:creator>Vahid Dejwakh</dc:creator>
      <pubDate>Fri, 28 Aug 2020 20:15:32 +0000</pubDate>
      <link>https://dev.to/dej/what-s-the-difference-between-a-framework-and-a-library-1cgi</link>
      <guid>https://dev.to/dej/what-s-the-difference-between-a-framework-and-a-library-1cgi</guid>
      <description>&lt;p&gt;This article originally appeared at &lt;a href="https://vahid.blog"&gt;https://vahid.blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's a framework? What's a library? Aren't the two terms interchangeable? Is React a framework or a library? What about NodeJS? And what's Rails? Who cares, anyway? So many good questions, you have.&lt;/p&gt;

&lt;p&gt;Answers, I shall offer you. &lt;/p&gt;

&lt;p&gt;Let's actually answer the &lt;em&gt;last&lt;/em&gt; question first, because it's the most important: why should you care about the difference? &lt;/p&gt;

&lt;p&gt;Knowing the difference will help you better understand how to make sense of all the existing resources currently available for web application development, and all future resources that are sure to keep popping up. &lt;/p&gt;

&lt;p&gt;Moreover, understanding whether each resource is a framework or a library will help you determine whether you can mix them together in the same application. For example, can you mix Angular and Express? Rails and React? Angular and React? Rails and Express? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Here's a hint&lt;/em&gt;&lt;/strong&gt;: you usually cannot or should not mix two frameworks together, but you can (and usually have to) mix a framework and a library. Indeed, you usually need to combine your framework with &lt;em&gt;multiple&lt;/em&gt; libraries, because each library does one thing well, and an application often makes use of many libraries because it needs to do many things well. &lt;/p&gt;

&lt;p&gt;The most significant technical difference between a framework and a library is who's in control of the execution flow. With a library, you're in control: you determine when to call the library, if at all. When working in a framework, however, you write code to fill in the gaps of the framework, because the framework is in control of the execution flow. The framework calls the code that you write.&lt;/p&gt;

&lt;p&gt;As the saying goes: you call the library -- &lt;em&gt;but the framework calls&lt;/em&gt; &lt;strong&gt;&lt;em&gt;you&lt;/em&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Both libraries and frameworks are installed the same way (e.g. as a package in Node.js, or a gem in Ruby). Both may also further be categorized as either advancing the front-end (client-side) or the back-end (server-side) of the application, or &lt;em&gt;both&lt;/em&gt; (fullstack).&lt;/p&gt;

&lt;p&gt;The last important distinction to make is that a framework can either be &lt;strong&gt;heavy&lt;/strong&gt; or &lt;strong&gt;light&lt;/strong&gt;, depending on how many restrictions and conventions it imposes on you. Using a heavy framework allows you to quickly ramp up and ship an application because the framework comes with significant pre-built scaffolding that you don't have to worry about creating from scratch. The drawback of a heavy framework is more rules and conventions you have to follow. &lt;/p&gt;

&lt;p&gt;Using a light framework means you can customize more things, and structure them however you want, but it also requires more time and more effort. Some heavy frameworks are built on top of light frameworks--i.e., they simply add more structure on top of the original scaffolding provided by the light framework. &lt;/p&gt;

&lt;p&gt;Here are some of the most popular frameworks and libraries, including initial release year.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://expressjs.com/"&gt;Express&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2010&lt;/td&gt;
&lt;td&gt;Javascript&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;Light&lt;/em&gt; Framework&lt;/td&gt;
&lt;td&gt;Minimalist back-end framework for web and mobile applications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2013&lt;/td&gt;
&lt;td&gt;Javascript&lt;/td&gt;
&lt;td&gt;Library&lt;/td&gt;
&lt;td&gt;Component-based front-end library supported by Facebook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://angular.io/"&gt;Angular&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2016&lt;/td&gt;
&lt;td&gt;Javascript&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;Light&lt;/em&gt; Framework&lt;/td&gt;
&lt;td&gt;Component-based front-end framework supported by Google&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.gatsbyjs.com/"&gt;Gatsby&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;Javascript&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;Light&lt;/em&gt; Framework&lt;/td&gt;
&lt;td&gt;React-based static site generator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://jquery.com/"&gt;jQuery&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2006&lt;/td&gt;
&lt;td&gt;Javascript&lt;/td&gt;
&lt;td&gt;Library&lt;/td&gt;
&lt;td&gt;Feature-rich library to facilitate DOM traversal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://sailsjs.com/"&gt;Sails&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2012&lt;/td&gt;
&lt;td&gt;Javascript&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;Heavy&lt;/em&gt; Framework&lt;/td&gt;
&lt;td&gt;Fullstack application development following the MVC model (built on top of Express)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://rubyonrails.org/"&gt;Rails&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2004&lt;/td&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;Heavy&lt;/em&gt; Framework&lt;/td&gt;
&lt;td&gt;Fullstack application development following the MVC model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/sinatra/sinatra"&gt;Sinatra&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2007&lt;/td&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;Light&lt;/em&gt; Framework&lt;/td&gt;
&lt;td&gt;Minimalist back-end framework for web and mobile applications&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's a good list of the main frameworks for the Javascript (Node.js) and Ruby ecosystems. Note that I didn't include many libraries, but that's because there are thousands. I included React because it is commonly misunderstood as a framework, and jQuery because of its importance to the subsequent development of Javascript-based paradigms, even though this success has also caused its own demise.&lt;/p&gt;

&lt;p&gt;A few notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usually, you wouldn't mix two frameworks together. However, the exception in the list above is that you can mix Express and Angular (the "M &lt;strong&gt;EA&lt;/strong&gt; N" stack)--but that's because they're both light frameworks, and they each focus on a different side of the application. &lt;/li&gt;
&lt;li&gt;It wouldn't make sense to mix Angular and React, although one is a framework and the other is a library, because they both provide front-end rendering paradigms. &lt;/li&gt;
&lt;li&gt;You could combine Express and React, however--and many indeed do (the "M &lt;strong&gt;ER&lt;/strong&gt; N" stack). &lt;/li&gt;
&lt;li&gt;You can mix Rails and React, since one is a heavy framework for fullstack applications, and the other is a library for front-end rendering. You wouldn't want to mix Rails and Express, however, since they both provide back-end frameworks.&lt;/li&gt;
&lt;li&gt;Sails is just one example of a heavy framework built on top of Express. There are &lt;a href="https://expressjs.com/en/resources/frameworks.html"&gt;many more&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/"&gt;NodeJS&lt;/a&gt; is neither a framework nor a library. It's a server-side runtime environment for Javascript (i.e. running JS outside of the browser). Node is what allows and powers the JS-based back-end frameworks above.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quiz time: could you mix Sinatra and Angular? Why/Why not? Leave a comment below.&lt;/p&gt;

</description>
      <category>framework</category>
      <category>library</category>
      <category>react</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
