<?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: Harriet</title>
    <description>The latest articles on DEV Community by Harriet (@harri_etty).</description>
    <link>https://dev.to/harri_etty</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%2F119015%2Fc849cdaf-c2da-4b69-94e2-23ad1db95807.jpg</url>
      <title>DEV Community: Harriet</title>
      <link>https://dev.to/harri_etty</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harri_etty"/>
    <language>en</language>
    <item>
      <title>What You Need to Know About Optimistic Concurrency</title>
      <dc:creator>Harriet</dc:creator>
      <pubDate>Wed, 27 May 2020 18:39:16 +0000</pubDate>
      <link>https://dev.to/harri_etty/what-you-need-to-know-about-optimistic-concurrency-1g3l</link>
      <guid>https://dev.to/harri_etty/what-you-need-to-know-about-optimistic-concurrency-1g3l</guid>
      <description>&lt;h3&gt;
  
  
  What is Optimistic Concurrency? First, a scenario...
&lt;/h3&gt;

&lt;p&gt;Imagine you are a humble bookseller and you have signed into your shop's stock management system. A customer has just called you to tell you they want to add 2 more copies of &lt;em&gt;Normal People&lt;/em&gt; to their order. You have their customer record open and you can see their order. They've already got a copy on order, but they've decided to give copies to their mother-in-law and their brother, too. It's just such a good book. While they're on the phone with you, they ask you to change the delivery address to their office, which you do, as well.&lt;/p&gt;

&lt;p&gt;However, whilst you're updating the order, your colleague has just got to work and has opened her inbox to see an email from the same customer that they sent over the weekend, before they decided it would just be easier to phone. And also at that point they were only thinking about their mother-in-law so they only asked for 1 extra copy. Your colleague actions the email, opening the customer record, and sees that 1 copy of &lt;em&gt;Normal People&lt;/em&gt; has been ordered, so she updates the total to 2. The email makes no mention of changing the delivery address so she doesn't touch that.&lt;/p&gt;

&lt;p&gt;Both you and your colleague have the order record open, and you have both made different changes. One of you is going to save the updated record first, and then the second person is going to save the record. Whose changes are going to "win"? Will the customer end up with 2 or 3 copies of &lt;em&gt;Normal People&lt;/em&gt; and will their books get sent to their home or office address?&lt;/p&gt;

&lt;p&gt;This scenario, where two or more people have got a copy of a record and are are about to overwrite the other person's changes, is pretty common. It is often called &lt;strong&gt;The Lost Update Problem&lt;/strong&gt; or a &lt;strong&gt;Mid-Air Collision&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/14jhYTxVkaOBl6/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/14jhYTxVkaOBl6/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We could simply say that the last person to submit the update "wins", but that wouldn't be great because we'd potentially loose a really important update that somebody else had attempted to make. In the above example, the humans involved know that the correct number of books is 3, because that was the most recent thing the customer said. But if your colleague made their update after yours, the order would end up with 2 books on it.&lt;/p&gt;

&lt;p&gt;There are two solutions to this problem, and &lt;strong&gt;Optimistic Concurrency&lt;/strong&gt; is one of them. &lt;strong&gt;Pessimistic Concurrency&lt;/strong&gt; is the other one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimistic Vs Pessimistic Concurrency
&lt;/h3&gt;

&lt;p&gt;Concurrency is the idea that two processes (in this case, updates) might be going on simultaneously.&lt;/p&gt;

&lt;p&gt;Both Optimistic and Pessimistic Concurrency offer solutions to deal with the conflicts that this concurrency might cause. They are both &lt;em&gt;concepts&lt;/em&gt; and don't prescribe specific technical implementations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optimistic concurrency&lt;/strong&gt; is the idea that these kinds of conflicts won't happen very often (hence it's "optimistic"), but when they do happen, the humans involved should be given the opportunity to react and decide what to do. In the above example, that means that if your colleague saved the record first, then when &lt;em&gt;you&lt;/em&gt; attempted to save the record afterwards you would be warned somehow, and would have to decide whether to overwrite the other changes or not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pessimistic Concurrency&lt;/strong&gt; assumes that these kinds of conflicts might occur regularly, and that it would be a pain to have to keep asking a human what to do, or perhaps not even feasible. A solution that employed pessimistic concurrency would need to ensure the system was protected from these kinds of conflicts ever happening. That generally means applying a "lock" to a record, so that if someone else is in the process of updating it, another person or system wouldn't be able to. In the above example, that means that your colleague wouldn't have been able to open the record while you were busy with it, thus preventing any possible conflicts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimistic Concurrency in Web Applications
&lt;/h3&gt;

&lt;p&gt;Web applications are one environment where pessimistic concurrency isn't really possible. This is because to maintain a "lock" on data in a database, the record would have to be kept in a "locked" state throughout the whole process of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You opening the record when the customer first calls you&lt;/li&gt;
&lt;li&gt;All the time you are updating the record&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lock would only be released when you are done with your call and you click the button to submit the Update request to the server. A fair amount of time could have passed without anyone else being able to update the record, which could easily cause a problem. And you might just get distracted and walk away, and then the lock would just stay in place until it expired at some point...&lt;/p&gt;

&lt;p&gt;In web applications, the app doesn't maintain a constant connection with the server or the database, so it's impossible to know whether you're still actually editing the record and the lock needs to remain, or whether you've gone off to do something else. In other kinds of applications, where the app is directly connected to the database, locking can be a solution, but not in web apps.&lt;/p&gt;

&lt;p&gt;Therefore we have to rely on Optimistic Concurrency, which means that we need a mechanism for identifying when these conflicting update requests happen, and ideally we need to bounce the problem back to the user for them to verify.&lt;/p&gt;

&lt;h3&gt;
  
  
  Isn't this just a merge conflict?
&lt;/h3&gt;

&lt;p&gt;If you've worked with Git and have experienced merge conflicts, then you might be thinking that this whole idea of multiple conflicting updates sounds pretty familiar - and you'd be right.&lt;/p&gt;

&lt;p&gt;Merge conflicts are a great example of &lt;strong&gt;Optimistic Concurrency&lt;/strong&gt; in action. Because Git by its nature is &lt;em&gt;distributed&lt;/em&gt; there's no way a single user could maintain a lock on a file they're editing, so the only solution is to allow multiple people to concurrently edit files, but when it comes to submitting those edits, if there are conflicts (to Git, this means lines of code which have been changed by two people) then the user submitting the most recent update is left with the oh-so-pleasant task of sorting out those conflicts and deciding which is the "right" version.&lt;/p&gt;

&lt;h3&gt;
  
  
  How is Optimistic Concurrency actually implemented?
&lt;/h3&gt;

&lt;p&gt;Technically, optimistic concurrency is usually implemented by using version numbers. Every record in a database will be given not only a unique &lt;code&gt;id&lt;/code&gt; but also a version number or timestamp. This means that every time a record is updated, logic can be executed that compares the version number of the record that its trying to save against the version that's stored in the database.&lt;/p&gt;

&lt;p&gt;In the above example, that means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You would have loaded version 1 of the record from the database&lt;/li&gt;
&lt;li&gt;Your colleague would have also loaded version 1&lt;/li&gt;
&lt;li&gt;You press "Save" first, making a request to update the record. The application submits the version number (1) along with the edits you want to make.&lt;/li&gt;
&lt;li&gt;The backend accepts the request and updates the record. This is now version 2 of the record.&lt;/li&gt;
&lt;li&gt;Your colleague presses "Save", making another request to update the record. The application submits the version number (1) along with the edits they want to make.&lt;/li&gt;
&lt;li&gt;The backend rejects the request, because it can see that version 1 is not the most up-to-date version.&lt;/li&gt;
&lt;li&gt;Your colleague is informed about the conflict and may be presented with an option to overwrite your changes, or resolve them.&lt;/li&gt;
&lt;/ul&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%2Fi%2F605wj8wqwq0zyr66hjvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F605wj8wqwq0zyr66hjvc.png" alt="The first request to update from V1 -&amp;gt; V2 is successful; the second is not, because V1 is no longer the most recent version number stored in the database. It must have changed whilst the second request was being made."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimistic Concurrency in action
&lt;/h3&gt;

&lt;p&gt;Here are a few examples of how various frameworks/technologies implement Optimistic Concurrency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DynamoDB&lt;/strong&gt; uses the mechanism of &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.ConditionalUpdate" rel="noopener noreferrer"&gt;Conditional Updating&lt;/a&gt;, where you can declare that the item should only be updated if certain values match what you expect. You could check a version number, or you could check that a property hasn't been changed by someone else.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rails uses version numbers, which it calls &lt;a href="https://blog.kiprosh.com/implement-optimistic-locking-in-rails/" rel="noopener noreferrer"&gt;Optimistic Locking&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Azure's CosmosDB gives every document an &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/database-transactions-optimistic-concurrency?irgwc=1&amp;amp;OCID=AID2000142_aff_7593_1243925&amp;amp;tduid=%28ir__spfhq39rt9kftkabkk0sohz3x22xni99q9xxsasq00%29%287593%29%281243925%29%28je6NUbpObpQ-eQuFHzSCimUVNDuxI6.GGA%29%28%29&amp;amp;irclickid=_spfhq39rt9kftkabkk0sohz3x22xni99q9xxsasq00#optimistic-concurrency-control" rel="noopener noreferrer"&gt;_etag&lt;/a&gt; property, which it updates automatically when the item is saved.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In fact, plain HTTP requests can implement &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag" rel="noopener noreferrer"&gt;etag response headers&lt;/a&gt;, which can also be used like version numbers to check whether a resource has been changed or not since it was last loaded. Frameworks like Java's Spring provide support for generating HTTP etags for resources available at URLs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Optimistic Concurrency on the frontend
&lt;/h3&gt;

&lt;p&gt;On the frontend it's really up to you how you handle optimistic concurrency!&lt;/p&gt;

&lt;p&gt;Assuming you receive a server error that you can identify as a concurrency error when trying to update an outdated record, it's up to you what you want to do.&lt;/p&gt;

&lt;p&gt;You might decide to tell the user that the record they're trying to update has been modified by someone else, and ask them to reload the page.&lt;/p&gt;

&lt;p&gt;Or you might provide a more interactive way for them to resolve the conflict, like some live document editing apps do - or think how Github allows you to resolve merge conflicts.&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%2Fi%2F6lqg62kaw5tqndvrzsuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6lqg62kaw5tqndvrzsuy.png" alt="Resolving a merge conflict through Github's web interface"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Not be be confused with.... Optimistic Updating
&lt;/h3&gt;

&lt;p&gt;Okay, one more thing! Optimistic concurrency isn't the same as optimistic updating.&lt;/p&gt;

&lt;p&gt;Optimistic updating is specifically a front-end concept and it means updating the UI before you've actually got confirmation from the server that the change was written to the database.&lt;/p&gt;

&lt;p&gt;In our humble bookseller example it would mean that after pressing "Save", the request is sent to the server but rather than wait the 500ms or whatever for a response, the frontend application updates the UI to show the changes as though everything was successful. As you can see, this is optimistic!&lt;/p&gt;

&lt;p&gt;Optimistic updating allows for a more fluid user experience. A great example is when making quick inline edits to a record, like editing a comment or upvoting an article. The edit/action results in a request to update the database record... but if you had to wait for confirmation before you saw your little "thumbs up" appear, the experience would feel very laggy.&lt;/p&gt;

&lt;p&gt;I hope this has been helpful, &lt;a href="https://twitter.com/harri_etty" rel="noopener noreferrer"&gt;follow me on Twitter&lt;/a&gt; and let me know if you have any comments 🤗&lt;/p&gt;

&lt;p&gt;NB. This was originally published at &lt;a href="https://www.harrietryder.co.uk/blog/optimistic-concurrency/" rel="noopener noreferrer"&gt;harrietryder.co.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>concurrency</category>
      <category>programming</category>
      <category>learntocode</category>
    </item>
    <item>
      <title>What did your onboarding documentation look like when you started your job?</title>
      <dc:creator>Harriet</dc:creator>
      <pubDate>Sun, 29 Mar 2020 18:14:29 +0000</pubDate>
      <link>https://dev.to/harri_etty/what-did-your-onboarding-documentation-look-like-when-you-started-your-job-28ko</link>
      <guid>https://dev.to/harri_etty/what-did-your-onboarding-documentation-look-like-when-you-started-your-job-28ko</guid>
      <description>&lt;p&gt;I'd love to know what onboarding materials were provided to you when you started your job. &lt;/p&gt;

&lt;p&gt;What does good documentation look like for getting started with a codebase? For getting started building features?&lt;/p&gt;

&lt;p&gt;It's common to receive documentation around getting your dev environment set up, and the basics of building/running/testing/deploying the software you'll be working on.&lt;/p&gt;

&lt;p&gt;But has anyone been provided with anything further? I'm imagining some "this is how we build stuff" documentation, detailing preferred patterns, or giving an introduction to the codebase, useful shared components, etc.&lt;/p&gt;

&lt;p&gt;How about "this is how we work" documentation - i.e. who approves PRs, how to ask for review, how long is acceptable to wait, how work gets assigned, etc. Has anyone ever been issued useful documentation around &lt;em&gt;process&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;If so, I'd love to hear&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What the project was (language, framework, basic function)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What general areas the documentation covered&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How useful the documentation was&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you have been involved in maintaining the documentation, how you have found that.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>discuss</category>
      <category>career</category>
      <category>onboarding</category>
    </item>
    <item>
      <title>Hiding Functionality Behind Feature Flags with Launch Darkly</title>
      <dc:creator>Harriet</dc:creator>
      <pubDate>Sun, 29 Mar 2020 17:56:50 +0000</pubDate>
      <link>https://dev.to/harri_etty/hiding-functionality-behind-feature-flags-with-launch-darkly-47i</link>
      <guid>https://dev.to/harri_etty/hiding-functionality-behind-feature-flags-with-launch-darkly-47i</guid>
      <description>&lt;p&gt;Originally published on my personal blog, &lt;a href="https://www.harrietryder.co.uk/blog/feature-flags-with-launch-darkly/"&gt;harrietryder.co.uk&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What are feature flags?
&lt;/h3&gt;

&lt;p&gt;In programming, a "flag" means a marker of some kind. Usually it's a boolean value - &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; which identifies or flags some piece of data as being in a certain state.&lt;/p&gt;

&lt;p&gt;A feature flag is a marker that identifies whether a specific feature should be available to the user of a piece software. If you want to enable a feature of your application for only specific users, you can employ the concept of a feature flag to indicate whether the feature should be enabled or not. This feature flag will either be &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; for a specific user, and your application logic should check this value before rendering any UI or performing any functionality related to the specified feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are the use cases for feature flags?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hiding features when not applicable to certain users:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine your application is a platform for collecting donations from donors around the world for numerous different charities. In the UK, there's a concept of Gift Aid, which allows charities to claim back tax on donations made from UK tax payers. So for a charity operating in the UK, it makes sense for the application to ask the donor if they are UK taxpayers. But for a charity operating in France, that option makes no sense and is just confusing. You could use a feature flag to decide whether, for this particular charity, you want to enable the Gift Aid feature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safety when rolling out new features:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another very common use case of feature flags is to provide some protection when rolling out or testing new features. It can be hard and slow to roll back a lot of changes relating to the implementation of a new feature, but if you can control a simple boolean value and easily switch it from &lt;code&gt;true&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; or vice versa, you have a really quick way of turning off a feature if it looks like it's going pear shaped or you want to pause it for a moment.&lt;/p&gt;

&lt;p&gt;The key is, your code needs to check the feature flag wherever there is some functionality relating to a given feature, so that turning the flag to &lt;code&gt;false&lt;/code&gt; will seem to remove the functionality. All the code and logic for the feature remains - you're not reverting any changes - it's just not accessible any more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Container&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;darkMode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DarkModeSelector&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Navigation&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Container&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&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;p&gt;&lt;strong&gt;A/B testing and percentage rollouts:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another use case is when you want to slowly expose your users to a new feature to begin gaining feedback/metrics before unleashing it on the whole world. For this, you might select an arbitrary percentage of users for whom to enable the given feature, and begin to up the % as you gain confidence. Or you might want to test 2 different variations of a feature (A/B testing) on two different segments, so you'd need to manage which users belonged to which segment through some kind of feature flag management.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Launch Darkly
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://launchdarkly.com/"&gt;Launch Darkly&lt;/a&gt; is a piece of software that enables you to manage feature flags in one place.&lt;/p&gt;

&lt;p&gt;You can set a list of flags through the Launch Darkly web application, obtain a client token, and using an SDK for your programming language of choice, access these flags anywhere in your frontend or backend code.&lt;/p&gt;

&lt;p&gt;One great feature about Launch Darkly is that its SDKs receive real-time updates whenever a flag changes. This means that even in a SPA, the end user will receive flag updates as soon as you change them on the Launch Darkly app, so you can turn features on/off immediately. You don't have to wait until a user does a hard page reload and fetches the flags again for the feature to turn off. When I first tried this out and saw how smoothly it worked, how the features just "popped off the page", it felt like magic!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QrtKNwdx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sdqas0fd3ai4lb5vanw1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QrtKNwdx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sdqas0fd3ai4lb5vanw1.png" alt="Launch Darkly Admin Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Launch Darkly users
&lt;/h3&gt;

&lt;p&gt;Not only can you turn featues on/off for your whole application, but you can manage features for specific users (i.e. the UK charities vs French charities example).&lt;/p&gt;

&lt;p&gt;To this end, Launch Darkly offers the concept of "users". You can create a Launch Darkly user (you'll want to create this user when a user signs up to your application). This Launch Darkly user is identifiable as that specific user in your application (most likely by ID), and you can also store other information against this user such as Country of Operation, age bracket, or any other custom piece of data that might help you evaluate whether they should be shown a feature or not. These users don't need to be (and probably shouldn't) be exact copies of the users you store in your own database - just store the info you need and don't store PII unless you absolutely need to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1y8izWZF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9szyb2uasqizt3typ9hi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1y8izWZF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9szyb2uasqizt3typ9hi.png" alt="Managing feature flags applied to users from the Launch Darkly dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the Launch Darkly dashboard, you can very easily apply feature flags to a selection of users based on the attribute you have stored about them (e.g. by country of operation), or by an abritrary percentage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing Environments
&lt;/h3&gt;

&lt;p&gt;Launch Darkly makes it super easy to manage environments - you get a different client key for each environment, so it's a piece of cake to have features turned on/off in different environments. For example, you want your Dark Mode feature turned on for all users in QA as you're testing it at the moment, but you can keep it turned off in Production for now until you're happy with it.&lt;/p&gt;

&lt;p&gt;You are probably loading different environment variables in different environments anyway so it should be simple to load a different Launch Darkly API key too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration in a React App
&lt;/h3&gt;

&lt;p&gt;Just so you can get a picture of how this looks from the front end, here are some contrived code examples.&lt;/p&gt;

&lt;p&gt;Imagine your backend has already done something like this upon signup to create a Launch Darkly user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aa0ceb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;country&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GB&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;custom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;groups&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Google&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Microsoft&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;ldClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Through the Launch Darkly dashboard you've enabled the "Gift Aid" feature for all users in GB.&lt;/p&gt;

&lt;p&gt;Your frontend React Application is wrapped in a Launch Darkly provider at the root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withLDProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;launchdarkly-react-client-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;withLDProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
  &lt;span class="na"&gt;clientSideID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-client-side-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When a users signs into your frontend application, you need to match them with the Launch Darkly user and retrieve their flags. In your sign-in success flow (within your wrapped &lt;code&gt;App&lt;/code&gt; component) you'll do something like this, to identify your current signed-in user with Launch Darkly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLDClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;launchdarkly-react-client-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ldClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLDClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onLoginSuccessful&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ldClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MainApp&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you don't have users, and you just have flags for your entire application, that's fine too, you can skip the &lt;code&gt;identify&lt;/code&gt; step above.&lt;/p&gt;

&lt;p&gt;Anywhere in your wrapped application you can use the &lt;code&gt;useFlags&lt;/code&gt; hook to obtain the flags for the current identified user or for the application as a whole. NB there is also a higher order component pattern that you can use - but in my view hooks are easier and nicer to use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFlags&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;launchdarkly-react-client-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;darkMode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFlags&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Container&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;darkMode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DarkModeSelector&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Navigation&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Container&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are various options for working with HOCs, async components or hooks in React, so you can use whichever pattern you prefer. There are also client-side and server-side SDKs for a large range of languages, &lt;a href="https://docs.launchdarkly.com/home/getting-started"&gt;see the docs&lt;/a&gt; for more information 🙂&lt;/p&gt;

</description>
      <category>featureflags</category>
      <category>launchdarkly</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The Three Month Rule of a New Job</title>
      <dc:creator>Harriet</dc:creator>
      <pubDate>Sat, 07 Mar 2020 19:55:11 +0000</pubDate>
      <link>https://dev.to/harri_etty/the-three-month-rule-of-a-new-job-ao3</link>
      <guid>https://dev.to/harri_etty/the-three-month-rule-of-a-new-job-ao3</guid>
      <description>&lt;p&gt;Originally published &lt;a href="https://www.harrietryder.co.uk/blog/3-month-rule/"&gt;on my personal blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've always maintained that it takes around 3 months, minimum, to begin to feel like you're really acing it in a new job. I'm speaking from the point of view of a software engineer, but perhaps it also holds true for any kind of more complex knowledge work, especially work that requires acquiring domain knowledge and close collaborative teamwork to do well.&lt;/p&gt;

&lt;p&gt;The figure of 3 months came from my own experiences, and from talking to many others. I admit, this figure is probably more biased towards people at the start of their careers, since I've worked with lots of people who've been getting their first, second or third jobs in tech and listened to their experiences. Maybe with more experience, in more leadership-style roles, you can expect to feel like you're doing your best work sooner. Maybe a consultant, brought in to help with a specific problem or help with their particular area of expertise, has a different experience. I'd really be interested to know.&lt;/p&gt;

&lt;p&gt;But for me, the figure of 3 months based mainly on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The need to learn the problem domain&lt;/strong&gt;. Unless you jump from one place to a competitor, solving a similar problem in a similar space, there will be a whole load of domain knowledge you need to pick up. For example, when I worked in analytics, I needed to learn about how digital marketing worked. Now I build a product for charities, I'm learning about how the charity sector works.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Figuring out the team dynamics&lt;/strong&gt;. Software engineering is so collaborative, you can't do your best job until you know how to best work with your team. You need to figure out who is good at what, who takes responsibility for various areas, how to get the best out of various people and just generally how to fit in. I've never joined a company where all this stuff is completely obvious, or documented in some workflow system - it always seems to require a mix of intuition, attention, experience to absorb.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learning the codebase&lt;/strong&gt;. Depending on the kind of work you need to do, the kind of tickets you get to work on, and the size of the project (or your area of it) this might be more or less challenging, but it's definitely still something that takes time. You can get a lot done in a codebase you don't fully understand but it won't be your best work. Even when you ask about things you don't understand, there will be a whole load of &lt;em&gt;unknown unknowns&lt;/em&gt;, such as what trade-offs were made at certain times, the fact that there is a component tucked away in an obscure project which does exactly what you're about to build, the fact that the tech lead has a handy bash script saved to parse those logs if you need it. You only pick these things up with time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learning new tools or technologies&lt;/strong&gt;. It's unlikely you'll jump from one place to another which uses the exact same tech stack in the exact same way, with the exact same tooling thrown in. So there's likely to be some ramp-up as you pick up these new things.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feeling confident in new responsibilities&lt;/strong&gt;. If you took a new role partly for career progression, then your responsibilities and job role might have changed, and then of course you might be partly learning on the fly how to do a whole new job!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I always found the figure of 3 months helpful, especially when talking to entry level developers, because I think it sets realistic expectations about how productive and useful you might feel at the beginning, and how much each role itself is different to other roles, and requires its own up-front learning before it can be done well.&lt;/p&gt;

&lt;p&gt;I'm not saying that after 3 months, you should feel like you can do the job with your eyes closed. But by that point, I think people are often beginning to feel more confident that they are valuable to their employer, know what they are capable of, are more aware of the areas they are less experienced in and might need help with, and are able to work more effectively with their team.&lt;/p&gt;

&lt;p&gt;I've changed jobs a few times during my career as as a software developer and only once did I feel like I could already do the job well on my first day. In retrospect, that was great for my employer and great for my self confidence, but not great for my personal/career growth.&lt;/p&gt;

&lt;p&gt;On the other hand, I've moved into roles where I very acutely felt that sense of "omg they're gonna fire me before I even hit the 3 month mark", which was challenging for my self-confidence but amazingly I never got fired, and grew a tonne instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can do
&lt;/h2&gt;

&lt;p&gt;I think on the whole, companies understand that there is a ramp-up period involved in on-boarding any employee, at any level of seniority. It would be expected that a more senior developer needs less support to get started, as they will have seen more patterns by which they can make sense of this particular project, and this particular way of doing things, worked with more different teams and hopefully be pretty good at picking up new tech. However, even so, all the above points still apply and you still won't be doing your best work immediately.&lt;/p&gt;

&lt;p&gt;On the other hand, I hear from a lot of developers earlier in their careers (and I include myself in this, 4 years in!) who find starting new jobs challenging, and beat themselves up over all the things they don't know straight away. That's why I find the 3-month rule helpful. If you keep the 3-month rule in your head, try to defer judgement on whether you're doing a good job or not until you pass that threshold. Then look back and ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What did I learn in the last 3 months?&lt;/li&gt;
&lt;li&gt;Am I doing a better job now, than 3 months ago?&lt;/li&gt;
&lt;li&gt;What do I want to get better at over the next 3 months?&lt;/li&gt;
&lt;li&gt;What was something that was really challenging 3 months ago? How much better/faster could I do that task now?&lt;/li&gt;
&lt;li&gt;What tickets have I closed/features have I worked on/successes have I had so far?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You still might be feeling out of your depth, but hopefully reflecting on how far you have already come, and knowing that it's totally normal and expected to feel like this, can help.&lt;/p&gt;

&lt;p&gt;And in another 3 months time, you can expect to ask yourself the same questions, and once again see that compared to 3 months ago, you've come leaps and bounds.&lt;/p&gt;

&lt;p&gt;You should also remember that we're not paid to just come in and bash out code. We're paid to solve the business problem, and that involves asking questions, being inquisitive, and thinking. The period we spend learning about a new company/problem/product is part of the job. We're also paid to keep up to date in our industry and make sure we're using the tools/technologies that can best solve the business problem, so it's totally normal that we're paid to be learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  What employers can do
&lt;/h2&gt;

&lt;p&gt;Obviously employers have a lot to answer to here as well, in terms of developing a positive onboarding experience that helps new hires do the best work they can do, at that point in time, and supports them in their ramp-up period.&lt;/p&gt;

&lt;p&gt;Larger companies might be able to provide specific training programmes for new employees, whereas smaller companies are more likely to implement pair programming as one of the principal methods of knowledge transfer.&lt;/p&gt;

&lt;p&gt;But it's also important to make sure that the work given to team members is suitable for someone who is learning a new codebase. Sometimes this work isn't the most valuable work but the net overall effect of easing someone into a new codebase/project in a sensible way is still greater than dumping a complicated, important problem on them.&lt;/p&gt;

&lt;p&gt;I'd love to hear examples around really positive onboarding experiences, as I'm lacking in anecdotal experience here 😂&lt;/p&gt;

&lt;h2&gt;
  
  
  Isn't this all a bit negative?
&lt;/h2&gt;

&lt;p&gt;Sometimes I feel like this 3-month rule can come across as a bit negative. Shouldn't we all be preaching positivity and a can-do attitude? You won't be awesome until you believe it yourself, right?&lt;/p&gt;

&lt;p&gt;But I think the alternative is more harmful, especially for people early in their careers or making career changes. There are enough reasons to second-guess yourself already, without unrealistic expectations about how quickly you can be doing your best work being thrown into the mix. If you're lucky and get a super supportive team who take great care to curate your work for you so that you're always pushed &lt;em&gt;exactly&lt;/em&gt; the right amount, and make you feel valuable from day 1, then you're one of the lucky ones. You can carry on feeling unexpectedly competent and confident and no harm done.&lt;/p&gt;

&lt;p&gt;But if you're like most people, working in an imperfect team in an imperfect world, you're likely to feel out of your depth at first, and if you're not prepared it can be a real challenge. You might think you're just not cut out for this work, or that you don't belong here, when actually you're just experiencing something totally normal.&lt;/p&gt;

&lt;p&gt;I'd really love to hear other experiences around this - especially from people who've never had this feeling, or people at other points in their career on whether a similar timeframe still holds true, and how you navigate it.&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>careerchangers</category>
    </item>
    <item>
      <title>The introduction to servers I wish I'd had</title>
      <dc:creator>Harriet</dc:creator>
      <pubDate>Sat, 09 Nov 2019 15:47:50 +0000</pubDate>
      <link>https://dev.to/harri_etty/the-introduction-to-servers-i-wish-i-d-had-44jl</link>
      <guid>https://dev.to/harri_etty/the-introduction-to-servers-i-wish-i-d-had-44jl</guid>
      <description>&lt;p&gt;When I first learned to code, I had no idea what a server was, what one looked like or how I would ever end up using one.&lt;/p&gt;

&lt;p&gt;In this guide, I'll try and provide the intro that I wish I'd had, and hopefully you'll end up with a better idea of what a server really is and how you can use one. These instructions should work whether you are on a Mac, Linux or Windows 10 machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  So, what is a server?
&lt;/h3&gt;

&lt;p&gt;You might read all sorts of technical explanations of what a server is, but I like to describe it as &lt;em&gt;a computer that's always connected to the internet&lt;/em&gt;. This is because it usually performs tasks that &lt;em&gt;need&lt;/em&gt; an internet connection, such as providing the files that make up a website. That's the scenario we'll work with for this article.&lt;/p&gt;

&lt;p&gt;When someone uses their web browser to request a website, a request is made to a specific server for the files that make up that website, and that server is always connected to the internet and is always ready to provide those files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n85hE2r4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mvt9fmc3aqzhn4d35oyc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n85hE2r4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mvt9fmc3aqzhn4d35oyc.png" alt="A request to a server"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is nothing special about that server apart from&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's always connected to the internet&lt;/li&gt;
&lt;li&gt;It's always on&lt;/li&gt;
&lt;li&gt;It's been configured to "listen" for requests and provide the right files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your own computer could be a server, if you really wanted.&lt;/p&gt;

&lt;p&gt;In reality, when we need a server we tend to rent one, or part of one, that's stored with many others in a big warehouse.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3DdIRvIH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fs5b6g9ugj6l9e1lxolk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3DdIRvIH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fs5b6g9ugj6l9e1lxolk.png" alt="Racks of servers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Servers don't have screens because humans don't need to interact with them through a graphical user interface. So you tend to see a load of them all stored efficiently together in racks.&lt;/p&gt;

&lt;h3&gt;
  
  
  So how do you get a server and configure it?
&lt;/h3&gt;

&lt;p&gt;If you want a server, these days you tend to go to a provider such as &lt;a href="https://aws.amazon.com/"&gt;Amazon Web Services&lt;/a&gt;, &lt;a href="https://cloud.google.com/gcp/"&gt;Google Cloud Platform&lt;/a&gt; or &lt;a href="http://digitalocean.com/"&gt;Digital Ocean&lt;/a&gt; and "provision" yourself a server.&lt;/p&gt;

&lt;p&gt;Let's do just that!&lt;/p&gt;

&lt;p&gt;Most of these platforms have free tiers for new users, or generous allowances for low-use customers.&lt;/p&gt;

&lt;p&gt;AWS allows new users a year of use of a small server, but even if you're not in your first year, we can create a server now and use it for a very short amount of time and it will only cost a few pennies.&lt;/p&gt;

&lt;h3&gt;
  
  
   Sign up with AWS
&lt;/h3&gt;

&lt;p&gt;If you haven't signed up for AWS before, &lt;a href="https://aws.amazon.com/"&gt;create an account&lt;/a&gt; now! You will need an active credit/debit card to sign up but we won't be doing anything that costs money.&lt;/p&gt;

&lt;h3&gt;
  
  
  Provision an instance
&lt;/h3&gt;

&lt;p&gt;AWS calls servers "instances" because technically you're not getting a server of your own, you're renting "compute space" in the cloud, in other words, a virtual server which is just a small slice of space on a single piece of hardware.&lt;/p&gt;

&lt;p&gt;But for all intents and purposes it feels like your own server. And it's much cheaper than buying a server just for yourself.&lt;/p&gt;

&lt;p&gt;First, find the service called &lt;em&gt;EC2&lt;/em&gt;:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gnx3KBOF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0ob05bc5s8o7fw8c813h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gnx3KBOF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0ob05bc5s8o7fw8c813h.png" alt="Select the EC2 Service"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, choose the option to launch an instance:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cib0Zx4v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/013qivbwobuxqzmafmho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cib0Zx4v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/013qivbwobuxqzmafmho.png" alt="Launch an instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are various types of instance you can choose, but only some are available in the free tier. Select the &lt;em&gt;Amazon Linux 2 AMI&lt;/em&gt; type which is an instance running the latest version of Amazon's Linux operating system. Most servers run a version of the Linux Operating System.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W0dlSw5B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9azga113c2vv5qat64kk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W0dlSw5B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9azga113c2vv5qat64kk.png" alt="Selecting Amazon Linux 2 AMI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next page, ensure the correct AMI type is still selected and press "Review and Launch":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zqyrAiWn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0fhfcu9792djnqy3c3sm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zqyrAiWn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0fhfcu9792djnqy3c3sm.png" alt="Review and Launch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you are asked whether to use an existing Key Pair or create a new one, &lt;em&gt;create a new one&lt;/em&gt; and &lt;em&gt;download it&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iTGYx1Kr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s4mx1nvihv78jo9f31f1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iTGYx1Kr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s4mx1nvihv78jo9f31f1.png" alt="Download new key file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your instance will then take a moment to provision, and when it does you'll be able to go to the EC2 dashboard and see a list of your running instances, probably only with 1 instance in it unless you already had some others running from before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connect to your instance
&lt;/h3&gt;

&lt;p&gt;We mentioned that instances don't have screens, so how can we operate them? We can remotely access and operate them from the command line, by connecting to them with a command called &lt;code&gt;ssh&lt;/code&gt;. SSH (Secure Shell) is a protocol for remotely and securely connecting to and operating computers across a network.&lt;/p&gt;

&lt;p&gt;When we use SSH to connect to our instance we will need to prove we actually have permission to take control of our instance. This is vital, or anyone could connect to our server and wreak havoc, especially since servers are usually doing business-critical, sensitive tasks such working with user data or payment details.&lt;/p&gt;

&lt;p&gt;When creating your instance you will have downloaded a private key. This key matches a public key, stored by AWS. Only the owner of the private key will be able to connect to the instance. This is called Public Key Authentication and is a standard method for authenticating with remote servers.&lt;/p&gt;

&lt;p&gt;First, maybe move this key file out of your Downloads directory to somewhere you'll know where to find it in the future, if you ever use it again.&lt;/p&gt;

&lt;p&gt;Then, we need to change the permissions on the file to make them more secure:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;chmod 400 my-first-key-pair.pem&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This means that it can only be read by the owner of the file.&lt;/p&gt;

&lt;p&gt;Finally, go to the AWS EC2 dashboard and find the public IP of the instance:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ASvxojbe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fo1x1xtqd70y4memrcuq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ASvxojbe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fo1x1xtqd70y4memrcuq.png" alt="Find the public IP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, use the IP to construct the below command, making sure you are providing the correct path to your .pem certificate file which you just modified, and substituting the IP address "34.244.187.6" for your instance's:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ssh -i my-first-key-pair.pem ec2-user@34.244.187.6&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When asked whether you want to continue, type "yes" and hit enter.&lt;/p&gt;

&lt;p&gt;You are now connected to your EC2 instance!&lt;/p&gt;

&lt;p&gt;If you are using a Linux machine and you don't already have the &lt;code&gt;ssh&lt;/code&gt; command enabled, you might need to run the following commands to enable it first:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt update&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt install openssh-server&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now this command should work:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ssh -i my-first-key-pair.pem ec2-user@34.244.187.6&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Look around! Make some files!
&lt;/h3&gt;

&lt;p&gt;Your terminal is now behaving as though it is the terminal connected to your EC2 instance. If you &lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;pwd&lt;/code&gt; you will see that it is not your computer any more. Feel free to make some files, explore the file system.&lt;/p&gt;

&lt;p&gt;There are no files in your home directory as it's a completely new instance but you will see plenty of standard linux files if you move to the root directory &lt;code&gt;cd /&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making our instance serve a website
&lt;/h3&gt;

&lt;p&gt;If we want to configure this instance to serve a website we have a do a few things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Allow HTTP connections, as browsers request websites using the HTTP protocol and currently our instance only allows SSH connections&lt;/li&gt;
&lt;li&gt;Configure some server software that will respond to HTTP requests by serving files&lt;/li&gt;
&lt;li&gt;Create these files (or get them onto the machine somehow)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's do these three things...&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Allow web traffic to your instance
&lt;/h3&gt;

&lt;p&gt;To allow web traffic we need to configure the "security group" settings of the instance. Click on the link to "launch wizard" next to the "Security Groups" heading on the EC2 dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iXD1qsYx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nwckamtjhtxyjyd595sb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iXD1qsYx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nwckamtjhtxyjyd595sb.png" alt="Find the security group settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the Security Groups page, ensure your security group is highlighted and then select the &lt;em&gt;Inbound&lt;/em&gt; tab, and press &lt;em&gt;Edit&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q0K8NuSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3o25psl0lufrg6zxe334.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q0K8NuSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3o25psl0lufrg6zxe334.png" alt="Edit Inbound Traffic Rules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add a new HTTP rule and leave the default settings that are provided. This will allow HTTP traffic into the instance from any IP address:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G5RCRjJ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cpaqkoj30zr84wzrkrd1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G5RCRjJ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cpaqkoj30zr84wzrkrd1.png" alt="Add a new rule"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save this new rule.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Install Apache
&lt;/h3&gt;

&lt;p&gt;Back in the terminal which has an SSH session established with your instance, run the following command to install a piece of software called Apache. Apache is a simple server software, and its default configuration allows it to serve static files for a single website when the instance receives HTTP requests on port 80, i.e. requests from browsers or other web clients.&lt;/p&gt;

&lt;p&gt;We can use the &lt;code&gt;yum&lt;/code&gt; package manager to install &lt;code&gt;httpd&lt;/code&gt; which is the package name for Apache, weirdly.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo yum install -y httpd&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Create some files
&lt;/h3&gt;

&lt;p&gt;By default Apache will serve files that are created in the &lt;code&gt;/var/www/html/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into that directory and create an &lt;code&gt;index.html&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd /var/www/html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo touch index.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To edit this file we will have to use a command-line editor such as Vim, because we have no graphical user interface, therefore no VSCode etc!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo vi index.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you haven't used Vim before, you need to toggle insert/command mode using the key &lt;code&gt;i&lt;/code&gt; to enter Insert mode and the Escape key to enter command mode.&lt;/p&gt;

&lt;p&gt;Once in insert mode, create your HTML file, and when done, toggle to command mode and type &lt;code&gt;:wq&lt;/code&gt; to save and quit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FYG6RLwG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0bmvs676xazdtw530sb4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FYG6RLwG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0bmvs676xazdtw530sb4.png" alt="Creating a HTML file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  One final step: Start the server
&lt;/h3&gt;

&lt;p&gt;We must start the Apache server software by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo service httpd start&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Visit the website
&lt;/h3&gt;

&lt;p&gt;Finally, we should be able to go to our instance's public IP address in the browser and the website should be served!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wcs0ATgH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4ebcpm021tbnyhfq0hgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wcs0ATgH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4ebcpm021tbnyhfq0hgc.png" alt="Visiting our website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are many more ways a server can be configured, and servers can do much more than serve a static web application - most of the time they run an application that performs some logic alongside serving static files, and often they are not used to serve an web application at all.&lt;/p&gt;

&lt;p&gt;However, I hope this has been a useful insight into just one way that a server can be configured.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disconnect from your instance
&lt;/h3&gt;

&lt;p&gt;To end your SSH session, hit they key combination &lt;code&gt;ctrl + D&lt;/code&gt; in the terminal. You should be back on your own computer now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terminate your instance
&lt;/h3&gt;

&lt;p&gt;To avoid charges, don't forget to terminate your instance when you're done!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H5L7QD74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/y2jrka9hfi9k3h5q50hh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H5L7QD74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/y2jrka9hfi9k3h5q50hh.png" alt="Terminate your instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can do this from AWS's EC2 dashboard. Terminating completely destroys the instance, or if you want to come back to it later you can "Stop" it and restart it again in the future. A stopped instance does not accrue charges.&lt;/p&gt;

</description>
      <category>servers</category>
      <category>aws</category>
      <category>ec2</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Maybe I Should Have Just Used create-react-app</title>
      <dc:creator>Harriet</dc:creator>
      <pubDate>Wed, 08 May 2019 07:57:06 +0000</pubDate>
      <link>https://dev.to/harri_etty/maybe-i-should-have-just-used-create-react-app-56af</link>
      <guid>https://dev.to/harri_etty/maybe-i-should-have-just-used-create-react-app-56af</guid>
      <description>&lt;p&gt;I've recently been working on improving the performance of a personal side project I've been working on, &lt;a href="http://conju-gator.com"&gt;Conju-gator.com&lt;/a&gt;, a little app for practicing verb conjugations in Spanish.&lt;/p&gt;

&lt;p&gt;The app is built in React with webpack as the bundling tool, the static files are served from Amazon's S3 with CloudFront content delivery network in front. When developing with React it is common to end up bundling all your source files and dependencies into one single JavaScript file called a bundle. The amount of JavaScript you serve is known to be a probable cause of performance issues, since the bundle can grow quickly as you pull in more and more dependencies.&lt;/p&gt;

&lt;p&gt;Originally I didn't give much thought to performance as it seemed like a tiny project, with very few source files and not many dependencies, and I thought performance would be something that I wouldn't need to worry about until later.&lt;/p&gt;

&lt;p&gt;However, the site does rely on a fairly large quantity of verb data to produce the training questions, which initially was a JSON file that I imported and bundled along with the source code, and thus could potentially cause performance problems at some point.&lt;/p&gt;

&lt;p&gt;I decided to run Chrome's Lighthouse performance audit (a brilliant tool) and get a benchmark for how my site was doing and to my horror it scored 0% on the audit!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JSx1supe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/93wl6ceoyli8h80xzoak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JSx1supe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/93wl6ceoyli8h80xzoak.png" alt="Chrome's Lighthouse auditing tools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What I was doing wrong
&lt;/h4&gt;

&lt;p&gt;The audit highlighted a few key areas where I could make improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code was not minified&lt;/li&gt;
&lt;li&gt;JavaScript payload was excessive&lt;/li&gt;
&lt;li&gt;Non-essential CSS was not being deferred&lt;/li&gt;
&lt;li&gt;Files were not served with an efficient cache policy&lt;/li&gt;
&lt;li&gt;Files were not zipped with gzip or equivalent before serving&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final two points were issues that I needed to fix at the S3/CloudFront level since they are server settings. The solution involved adding metadata to the objects I uploaded to S3 to ensure they were served with a max-age Cache Control header, and that they could be served gzipped. With these two fixes my audit improved about 50%.&lt;/p&gt;

&lt;p&gt;The issue of non-essential CSS being loaded too early when it could be deferred I ended up solving with &lt;a href="https://github.com/typekit/webfontloader"&gt;Google Web Font Loader&lt;/a&gt; although I also came across other &lt;a href="https://www.filamentgroup.com/lab/async-css.html"&gt;approaches to loading async CSS&lt;/a&gt; which may also have been useful. The CSS changes didn't make a big difference in the audit.&lt;/p&gt;

&lt;h4&gt;
  
  
  Webpack Improvements
&lt;/h4&gt;

&lt;p&gt;The first two issues, however, are the ones I want to talk about as they have to do with bundle size. I was serving a &lt;strong&gt;3000kb&lt;/strong&gt; JavaScript bundle, and when you think that the recommended size is &lt;strong&gt;&amp;lt; 250kb&lt;/strong&gt;, you can see how off the mark I was.&lt;/p&gt;

&lt;p&gt;Firstly, my code was not &lt;strong&gt;minified&lt;/strong&gt;, which was an easy mistake to fix as there is a &lt;a href="https://github.com/webpack-contrib/babel-minify-webpack-plugin"&gt;webpack plugin&lt;/a&gt; that'll do the job for you, or if you're using webpack in production mode then minification comes by default!&lt;/p&gt;

&lt;p&gt;That's another issue - I wasn't &lt;strong&gt;using production mode&lt;/strong&gt; when building my bundle for production. A single line: &lt;code&gt;mode: "production"&lt;/code&gt; in my webpack configuration solved so many problems - it brought the bundle size down considerably by only including the parts of libraries that were needed for production, and also gave me minification for free. Webpack's &lt;a href="https://webpack.js.org/guides/production/"&gt;guide to bundling for production&lt;/a&gt; is extremely clear and helpful and I wish I'd read it earlier!&lt;/p&gt;

&lt;p&gt;Off the back of more research, I also decided to &lt;strong&gt;remove source mapping&lt;/strong&gt; in production (the webpack guide suggests to keep it, for debugging purposes, but to use a lightweight version). Source mapping maintains a map from your bundled code to your original source files so that line numbers &amp;amp; file names in the console refer to your &lt;em&gt;original&lt;/em&gt; files and not the bundle. However I wanted to cut down my bundle as much as possible so removed it completely and will bring it back if needed.&lt;/p&gt;

&lt;p&gt;By using &lt;a href="https://www.npmjs.com/package/webpack-bundle-analyzer"&gt;Webpack Bundle Analyser&lt;/a&gt; I was able to watch as my bundle size decreased, and see where its size was coming from.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B3Bh3wc2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dxh1dfo2a7ekmmu8akei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B3Bh3wc2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dxh1dfo2a7ekmmu8akei.png" alt="Analyzing the bundle size"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the analyzer showed me that my node_modules were now taking up a reasonable amount of space compared to my source code, and my whole bundle size in production was under 250kb, I was pretty happy.&lt;/p&gt;

&lt;p&gt;Finally, I decided to remove the verb data from the bundle and fetch it asynchronously, although I'd already got to about 98% on the audit at this point and although it reduced my bundle size further it didn't give me any Lighthouse performance audit improvements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---Olasaz4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qaml75g53pfr2u0r9ef0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---Olasaz4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qaml75g53pfr2u0r9ef0.png" alt="My final performance audit score"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
   Reflections
&lt;/h4&gt;

&lt;p&gt;Looking back, the changes I made were quite straightforward and I feel foolish for not realising how bloated my bundle was in the first place. However, at the time it took me some solid hours of work to work through all my problems, and figure out the best solutions.&lt;/p&gt;

&lt;p&gt;At one point, I thought "I wish I'd just used create-react-app in the first place!" since CRA will provide default webpack configurations which would have surely been optimised for production and included all the things I'd originally omitted, plus more.&lt;/p&gt;

&lt;p&gt;However, the CRA webpack configuration is about 400+ lines long, which is one of the reasons I always shy away from using CRA in the first place. I like to know what my configuration is doing and be able to change it if I need to, and I've traditionally found the configuration of CRA apps hard to debug and maintain.&lt;/p&gt;

&lt;p&gt;What are your thoughts? Do you prefer an opinionated/optimised configuration at the expense of customisability?&lt;/p&gt;

&lt;p&gt;Have you had an experience of optimising performance on a single page React app?&lt;/p&gt;

&lt;p&gt;Am I missing any more performance wins?&lt;/p&gt;

&lt;p&gt;🙌&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webpack</category>
      <category>performance</category>
    </item>
    <item>
      <title>From JavaScript to Ruby: A few of my favourite features</title>
      <dc:creator>Harriet</dc:creator>
      <pubDate>Fri, 01 Feb 2019 12:47:22 +0000</pubDate>
      <link>https://dev.to/harri_etty/from-javascript-to-ruby-a-few-of-my-favourite-features-37mf</link>
      <guid>https://dev.to/harri_etty/from-javascript-to-ruby-a-few-of-my-favourite-features-37mf</guid>
      <description>&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fag34t8l3d6abb8onugfn.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fag34t8l3d6abb8onugfn.jpg" alt="Ruby"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Coming from JavaScript to Ruby, I was excited to learn the language that promised to be "friendly to developers" and "designed for developer happiness". I discovered a language which, like JS, is dynamic, object oriented and general purpose. Like JS, it also offers lots of ways to do the same thing, enabling the developer to have a fair amount of stylistic autonomy (if you like that kind of thing).&lt;/p&gt;

&lt;p&gt;Ruby has a fairly low learning curve, since it seems to have been designed with lots of sensibly-named, consistent and easy to use methods, and it also has no concept of asynchronicity out of the box, making code easier to reason about than JavaScript.&lt;/p&gt;

&lt;p&gt;Here are a few things I've noticed which I think are pretty neat about Ruby, in comparison to JavaScript!&lt;/p&gt;

&lt;h2&gt;
  
  
  Being able to check memory location
&lt;/h2&gt;

&lt;p&gt;Unlike in JavaScript, Ruby lets you inspect the location in memory of a value with the &lt;code&gt;object_id&lt;/code&gt; method:&lt;/p&gt;

&lt;p&gt;For example, if we look at the object ID of 2 hashes:&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Harriet'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Heather'&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;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object_id&lt;/span&gt; &lt;span class="c1"&gt;# 6478367&lt;/span&gt;
&lt;span class="nb"&gt;puts&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;object_id&lt;/span&gt; &lt;span class="c1"&gt;# 6471222&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those numbers are memory addresses. The actual addresses aren't that useful but it might help to see when you're dealing with two references to the same location in memory, or references to separate locations in memory.&lt;/p&gt;

&lt;p&gt;I've never used this in a practical sense, but it was helpful when I wanted to explore the difference in how Strings and Symbols work in Ruby (see next section). There's no way in JavaScript to inspect where items live in memory, which has been annoying when I've been trying to demonstrate how JavaScript passes objects by reference, and primitives by value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symbols
&lt;/h2&gt;

&lt;p&gt;In JavaScript, you have a few of ways of creating a string, the first two here being the most common:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// Functionally no different to using single quotes&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Creates a String object&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Hello world`&lt;/span&gt; &lt;span class="c1"&gt;// ES6 String Literal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Ruby, there are also a few options:&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hello world'&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello world"&lt;/span&gt; &lt;span class="c1"&gt;# Double quotes allow for string interpolation &amp;amp; escape characters&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&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;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello world'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello world'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Ruby, by default, all Strings are types of String Objects, and as Objects they occupy different places in memory, even if the contents of two or more strings is the same. Potentially a bit wasteful, storing the exact same information twice over!&lt;/p&gt;

&lt;p&gt;You can check this by looking at the object ID of 2 identical strings:&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hello world'&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hello world'&lt;/span&gt;
&lt;span class="nb"&gt;puts&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;object_id&lt;/span&gt; &lt;span class="c1"&gt;# 6478367&lt;/span&gt;
&lt;span class="nb"&gt;puts&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;object_id&lt;/span&gt; &lt;span class="c1"&gt;# 6471222&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s where Symbols come in. A Symbol is created with a : at the beginning and means that any time the Symbol is used, it will reference the same value.&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:hello&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:hello&lt;/span&gt;
&lt;span class="nb"&gt;puts&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;object_id&lt;/span&gt; &lt;span class="c1"&gt;# 1111708&lt;/span&gt;
&lt;span class="nb"&gt;puts&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;object_id&lt;/span&gt; &lt;span class="c1"&gt;# 1111708&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works great for single words, but you can even turn a longer string into a Symbol and increase efficiency with the &lt;code&gt;.to_sym&lt;/code&gt; method:&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hello world'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hello world'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;
&lt;span class="nb"&gt;puts&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;object_id&lt;/span&gt; &lt;span class="c1"&gt;# 92880&lt;/span&gt;
&lt;span class="nb"&gt;puts&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;object_id&lt;/span&gt; &lt;span class="c1"&gt;# 92880&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use symbols over strings wherever I can, not just when I know a value will be used again in a program! Why not, when it’s easy to do and there’s nothing to lose?&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple loops ➰
&lt;/h2&gt;

&lt;p&gt;In JavaScript, sometimes you just want to loop a set number of times. You don't care about the start point or the end point, as long as your code executes n times. However, you're forced to explicitly construct the conditions for iteration yourself, starting with i = 0 and defining when you want the loop to end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// do stuff&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Ruby, you can simply do:&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="mi"&gt;10&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="c1"&gt;# do stuff&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a simple, less imperative way of executing code a set number of times.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functions are stricter about arguments
&lt;/h2&gt;

&lt;p&gt;I like that in Ruby, you get an error if you give a function the wrong number of arguments. It just speeds up the process of debugging your code.&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;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&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="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# wrong number of arguments (given 0, expected 1)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also name your parameters, and if they're not passed, or you pass something unexpected, you'll get an error:&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;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;city&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="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Harriet'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;city: &lt;/span&gt;&lt;span class="s1"&gt;'Manchester'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Harriet'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# missing keyword: city&lt;/span&gt;

&lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Harriet'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;city: &lt;/span&gt;&lt;span class="s1"&gt;'Mancheseter'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age: &lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# unknown keyword: age&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  No function call parentheses
&lt;/h2&gt;

&lt;p&gt;In JavaScript, you must use parentheses when calling a function, for example &lt;code&gt;add(1, 2)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Ruby, parentheses are generally optional, which can sometimes lead to Ruby that looks very natural language-y and easy to read. For example, a testing library can provide a &lt;code&gt;to&lt;/code&gt; method which, when used without parentheses, reads like this:&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;expect&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="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be_null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although it can get a bit confusing if you've got multiple arguments. For example, is &lt;code&gt;5&lt;/code&gt; the second argument to &lt;code&gt;bar&lt;/code&gt;, or the second argument to &lt;code&gt;foo&lt;/code&gt;? Without brackets it's not clear:&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;foo&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="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"in foo &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;a&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;b&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="nf"&gt;bar&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="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="c1"&gt;# wrong number of arguments (given 2, expected 1)&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="c1"&gt;# Correct - 5 is the second argument to foo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling a function without parentheses also means we can do something like this:&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;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Harriet'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&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="n"&gt;greet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how just referring to the &lt;code&gt;greet&lt;/code&gt; method actually invokes it with no arguments? This is how Ruby implements getter methods on objects. When you call &lt;code&gt;person.name&lt;/code&gt; for example, &lt;code&gt;name&lt;/code&gt; is actually a method on that object, which retrieves the &lt;code&gt;name&lt;/code&gt; instance varaible. It's not simply an object property like in JavaScript.&lt;/p&gt;

&lt;p&gt;One effect of parentheses-less method calls means we can't pass methods around as values, like we can in JavaScript. In JavaScript, we can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;welcomer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;welcomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Harriet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But in Ruby, trying to pass a reference to the method actually invokes it! So we end up with:&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;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Harriet'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&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="n"&gt;welcome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt; &lt;span class="c1"&gt;# This line actually executes the greet function&lt;/span&gt;

&lt;span class="n"&gt;welcome&lt;/span&gt; &lt;span class="s2"&gt;"Paula"&lt;/span&gt; &lt;span class="c1"&gt;# undefined method `welcome' for main:Object&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Just one way to create Classes
&lt;/h2&gt;

&lt;p&gt;In JavaScript there is not really a concept of true classes, at least not in the way people from truly Object Oriented languages would expect them to be. Instead we have a the prototype chain, and at least 4 different ways of creating objects with shared methods and behaviour. This is super confusing, so I really like that Ruby just offers the one way to do it!&lt;/p&gt;

&lt;p&gt;Creating class methods, class variables, instance methods and instance variables is much more straightforward in Ruby:&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;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;

  &lt;span class="c1"&gt;# Class variables&lt;/span&gt;
  &lt;span class="vc"&gt;@@legs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="vc"&gt;@@arms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="vc"&gt;@@diet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'omnivore'&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&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="c1"&gt;# @name and @title are instance variables&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
    &lt;span class="vi"&gt;@title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Instance method&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Good day, &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; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&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="c1"&gt;# Class method&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"A person is a &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vc"&gt;@@legs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-legged, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vc"&gt;@@arms&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-armed &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vc"&gt;@@diet&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;end&lt;/span&gt;

&lt;span class="n"&gt;jerry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Jerry Jones'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Mr'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;jerry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;

&lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implicit returns
&lt;/h2&gt;

&lt;p&gt;In Ruby, the &lt;code&gt;return&lt;/code&gt; statement is optional, or can be used to return early from a function. If you omit it, the function will return the last evaluation.&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;double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&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;h2&gt;
  
  
  Metaprogramming
&lt;/h2&gt;

&lt;p&gt;This one's quite a big a topic and I don't know it that well so I'm only going to touch on it briefly. Metaprogramming means a program being able to modify itself at runtime, based on the state of the program at that time.&lt;/p&gt;

&lt;p&gt;Rails uses Metaprogramming to allow us to do something like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Book.find_by_ISBN("19742084746")&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You defined the &lt;code&gt;Book&lt;/code&gt; class when you set up your Models, but nowhere did you defined the &lt;code&gt;find_by_ISBN&lt;/code&gt; method. Defining a &lt;code&gt;find_by_x&lt;/code&gt; for all your columns would be really tiresome; it's no wonder the Rails framework doesn't want to make you go to all that work. But Rails itself didn't add that method for you, either. How would Rails magically know what your Book instances needed a &lt;code&gt;find_by_ISBN&lt;/code&gt; method?&lt;/p&gt;

&lt;p&gt;Instead, when Rails sees you trying to use the &lt;code&gt;find_by_ISBN&lt;/code&gt; method it will extract the &lt;code&gt;ISBN&lt;/code&gt; part and attempt to match it to a column in the database, and if successful, will execute some code to find your item based on the &lt;code&gt;ISBN&lt;/code&gt; column, responding as though &lt;code&gt;find_by_ISBN&lt;/code&gt; were an actual method that had been defined on Book instances.&lt;/p&gt;

&lt;p&gt;This is just one example of what Metaprogramming can do!&lt;/p&gt;

&lt;p&gt;Personally I think it's pretty cool, and once you know it exists, you begin seeing it "in the wild" all over the place in Ruby. It's the foundation stone for being able to create DSLs (Domain Specific Languages) like Rails and makes Ruby extremely flexible.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
