<?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: Erik</title>
    <description>The latest articles on DEV Community by Erik (@erikwhiting88).</description>
    <link>https://dev.to/erikwhiting88</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%2F204634%2Fe0f8a6f2-5fa9-4a3e-bea4-266f276a64a7.jpg</url>
      <title>DEV Community: Erik</title>
      <link>https://dev.to/erikwhiting88</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/erikwhiting88"/>
    <language>en</language>
    <item>
      <title>How to Start Contributing to Open Source Software</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Thu, 17 Oct 2024 20:27:52 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/how-to-start-contributing-to-open-source-software-kc8</link>
      <guid>https://dev.to/erikwhiting88/how-to-start-contributing-to-open-source-software-kc8</guid>
      <description>&lt;p&gt;I am pretty open with my enthusiasm for open-source software (OSS) and, as a result, often receive questions from others on how they can get started contributing to projects. I’ve received enough questions to notice some trends in where people are starting from and what kind of problems they’re having. As such, I wanted to write this article to help anyone who is wanting to get started contributing to OSS projects, because getting started is the hardest part! To begin, let’s briefly talk about the advantages of contributing to OSS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contribute to the Community
&lt;/h3&gt;

&lt;p&gt;One of the main reasons I like contributing to OSS projects is because I generally like being helpful. I enjoy fixing bugs that trip people up or adding features that help people get their work done more efficiently.&lt;/p&gt;

&lt;p&gt;I also like contributing specifically to my field. As a PhD student and possibly future scientist, I have a vested interest in the quality of the software in my field–specifically, structural bioinformatics. I use several tools in this field and often find areas that can be improved, both for myself and others. As an example, consider &lt;a href="https://github.com/biopython/biopython.github.io/pull/204" rel="noopener noreferrer"&gt;this minor documentation change I added to the Biopython documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is admittedly a very small change, however I updated documentation that was incorrect because on &lt;em&gt;two&lt;/em&gt; separate occasions, I landed on this page while trying to do something and got errors by following the provided example. In the future when I (or anyone else) arrive at this page, they will not have to go through the trouble of debugging the examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Develop or Hone new Skills
&lt;/h3&gt;

&lt;p&gt;This is one of the primary direct benefits of contributing to OSS projects–the chance to work on significant projects with technologies you’re interested in working with. This can be fun for you and it can also help provide “proof” that you know how to work with certain technologies even though your work life might not provide you with exposure to them.&lt;/p&gt;

&lt;p&gt;One personal example, doing &lt;a href="https://github.com/OpenMS/autowrap/pull/159" rel="noopener noreferrer"&gt;this PR adding support for some operators to the autowrap project&lt;/a&gt; gave me the chance to learn a lot about Cython and work with a small bit of C++. Another example from the Biopython ecosystem is &lt;a href="https://github.com/biopython/biopython/pull/3787" rel="noopener noreferrer"&gt;this PR updating the documentation-deployment process&lt;/a&gt;. This work was one of my first exposures to working with CI/CD systems, a topic I feel I excel in now. Being able to deliver this feature on a project that impacts many people was a very valuable and fun learning experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Develop a Name for Yourself
&lt;/h3&gt;

&lt;p&gt;Another benefit to contributing to OSS projects is making a name for yourself in a certain area. For example, many of the frequent contributors to the CPython project become Python fellows or contributing members. This designation signals a kind of proven competence. Anyone who regularly contributes to CPython must be either an expert in Python, C, or both, right?&lt;/p&gt;

&lt;p&gt;Being known as a helpful presence in some software community will garner goodwill for yourself, and that goodwill can go a long way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up your GitHub Profile
&lt;/h2&gt;

&lt;p&gt;Now that we know &lt;strong&gt;&lt;em&gt;why&lt;/em&gt;&lt;/strong&gt; we want to contribute to open-source software, lets finally get to &lt;strong&gt;&lt;em&gt;how&lt;/em&gt;&lt;/strong&gt;. The very first thing you need to do, if you haven’t already, is set up your GitHub account. You can also additionally set up a GitLab account if you know the project you want to which you want to contribute is hosted there.&lt;/p&gt;

&lt;p&gt;There’s really no beating &lt;a href="https://docs.github.com/en/get-started/onboarding/getting-started-with-your-github-account" rel="noopener noreferrer"&gt;the official documentation from GitHub on setting up your account&lt;/a&gt;, so I wont’ write out all the steps here. Follow the steps in that link so you can start contributing.&lt;/p&gt;

&lt;p&gt;If you’re new to Git, feel free to check out my professional git series (&lt;a href="https://erikscode.space/index.php/2021/03/26/professional-version-control-with-git-pt-1-the-basics/" rel="noopener noreferrer"&gt;part 1&lt;/a&gt;, &lt;a href="https://erikscode.space/index.php/2021/04/05/professional-version-control-with-git-pt-2-collaboration/" rel="noopener noreferrer"&gt;part 2&lt;/a&gt;, &lt;a href="https://erikscode.space/index.php/2021/04/16/professional-version-control-with-git-pt-3-rebase-and-bisect/" rel="noopener noreferrer"&gt;part 3&lt;/a&gt;), which should teach you all you’ll need to know about working with Git and contributing to OSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picking a Project
&lt;/h2&gt;

&lt;p&gt;Perhaps the most important step is the first: picking a project to contribute to. This is where I see a lot of aspiring OSS contributors quit before they even start, but it’s not their fault! Often, the advice to people just finishing learning the basics is to find an OSS project in that language and “just start contributing!” Personally, I find this advice unhelpful because it can send inexperienced learners towards complex projects they’re likely not ready for.&lt;/p&gt;

&lt;p&gt;As an example, when I first learned Python, someone suggested that I start contributing to &lt;a href="https://github.com/django/django" rel="noopener noreferrer"&gt;Django&lt;/a&gt;. Django is a web development framework for Python and it’s incredibly popular, but it was way over my head at the time as I had just finished an introductory level book on Python development and had absolutely no experience. I didn’t even know how to use Django, let alone contribute to it. My inability to even figure out how to get Django running locally put me off OSS development for a long time. My point here is, don’t just browse GitHub and start trying to make sense of the most popular project written in your language of choice, find a project that really interests you.&lt;/p&gt;

&lt;p&gt;I believe the trick to being a frequent contributor to a project is caring enough about it to stick with it. You will likely never make meaningful contributions to a project in just a few hours of work, you will likely spend days or weeks on fixing bugs and adding features; and that’s &lt;strong&gt;&lt;em&gt;after&lt;/em&gt;&lt;/strong&gt; you’ve spent a bunch of time figuring out how the software works as is. So, you need to find a project that you are interested in enough to work on for extended periods of time.&lt;/p&gt;

&lt;p&gt;Caring about a project requires one of two things: investment in the problem being solved by the project, or an interest in the work itself. To illustrate the first point, consider Biopython. Most of the contributors to that project are bioinformatics researchers. For the second point, consider the fact that many contributors to open source programming languages (like &lt;a href="https://github.com/python/cpython" rel="noopener noreferrer"&gt;CPython&lt;/a&gt;, &lt;a href="https://github.com/rust-lang/rust" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;, and more) are language enthusiasts that contribute because they like the kinds of challenges language design presents.&lt;/p&gt;

&lt;p&gt;Since finding a project to contribute to is so important, take your time doing it. There’s no reason you have to decide today what project you want to contribute to. Browse different topics in GitHub and see what sparks your interest the most.&lt;/p&gt;

&lt;h2&gt;
  
  
  Figuring out the Development Workflow
&lt;/h2&gt;

&lt;p&gt;Once you’ve found a project to contribute to, the next step is figuring out how the project’s community builds their software. If you want to contribute to their work, you have to respect their process. Often, this will be explained in a file called &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; or something similar.&lt;/p&gt;

&lt;p&gt;The kinds of things you want to look out for is how the community prefers to receive pull requests. For some, maintainers want all pull requests to be associated with a corresponding GitHub issue. For example, this &lt;a href="https://github.com/OBOFoundry/OBOFoundry.github.io/pull/2594" rel="noopener noreferrer"&gt;pull request to the OBOFoundry home page&lt;/a&gt; removes a page from their website, but I only made this PR because one of the maintainers created &lt;a href="https://github.com/OBOFoundry/OBOFoundry.github.io/issues/2590" rel="noopener noreferrer"&gt;issue 2590&lt;/a&gt; in the “Issues” tab asking for that page to be removed.&lt;/p&gt;

&lt;p&gt;The most common workflow I’ve encountered involves forking the main repository into your own profile, creating a branch based on some issue, making your changes, writing tests for the changes, and making a pull request to the main repo. Development workflows frequently include a CI pipeline with tests and checks your changes have to pass.&lt;/p&gt;

&lt;p&gt;More often than not, the final step in the development workflow is a review process. This typically includes a project maintainer looking over your changes and making sure you’ve solved the problem and that your code code is in line with project’s standards. This is usually a back-and-forth process, especially for your first contribution, in which a reviewer may ask you for changes multiple times. Don’t get discouraged or take these reviews personally! This is someone else’s project after all, you are a guest (though a helpful one!).&lt;/p&gt;

&lt;p&gt;Project’s sometimes have guidelines for tagging reviewers (mentioning their GitHub username so they’re notified that you’re awaiting their review) so your work can move forward. Don’t get impatient and tag reviewers constantly, but don’t be too shy to bump your PR if the guidelines allow for it.&lt;/p&gt;

&lt;p&gt;The main takeaway here is to set yourself up to be a productive member of the project community by adhering to their process and not just diving in headfirst writing code and making changes that no one wants. Remember, software engineering is a collaborative process, even (or especially!) in open source development.&lt;/p&gt;

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

&lt;p&gt;Contributing to OSS can be beneficial to you, project maintainers, and the general public alike. It can also be a lot of fun! Remember to carefully choose the projects you want to contribute to and respect the development process. Feel free to reach out if you have any questions.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>An Introduction to Software Architecture</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Tue, 26 Sep 2023 06:08:40 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/an-introduction-to-software-architecture-18he</link>
      <guid>https://dev.to/erikwhiting88/an-introduction-to-software-architecture-18he</guid>
      <description>&lt;p&gt;Software architecture is the concept of how a software project is structured; a holistic view of the entire system including class hierarchies, interface design, even deployment patterns. A system’s architecture impacts nearly every facet of interaction with that system, from end users to the developers that build and maintain it. When you understand your system’s architecture, you’ll develop an intuition for estimating the time it will take to build new features, where bugs may be hiding in the code, and how to influence the performance of your system. In order to give you the tools to study the architecture of the projects you’ll one day be contributing to, this article lays a foundation for the most important concepts related to the topic, namely architectural patterns, reusability, quality attributes, and tradeoffs.&lt;/p&gt;

&lt;p&gt;It is difficult to find a helpful and exact definition for software architecture that accurately communicates its importance and prevalence. One simple definition of software architecture might be “the structure of a software system.” But that definition lacks the gravitas the concept deserves.&lt;/p&gt;

&lt;p&gt;More colloquially, you will often hear people define software architecture as “the stuff that’s expensive to change later.” Such a definition, while true, doesn’t really tell us much about what it is. For example, the programming language in which a system is written is expensive to change, but so is the application’s project management software (for example, moving from internal documents to a professional project management system like Jira is very expensive). These are both expensive things to change, but only the programming language is a facet of software architecture.&lt;/p&gt;

&lt;p&gt;In truth, software architecture means different things to different people and there is no universal definition that all developers will agree on. To some, software architecture is similar to class design in that it models the relationships between classes throughout the entire system.&lt;/p&gt;

&lt;p&gt;Others extend the concept to include not only class relationships, but also the infrastructure upon which the system runs such as the type of database a system might use or the type of web server.&lt;/p&gt;

&lt;p&gt;An official definition for software architecture exists in a document from the International Organization for Standardization (ISO) in conjunction with the International Electrotechnical Commission (IEC) and the Institute of Electrical and Electronics Engineers (IEEE) called &lt;strong&gt;&lt;em&gt;ISO/IEC/IEEE 42010:2022 – Systems and software engineering – Architecture Description&lt;/em&gt;&lt;/strong&gt;. This standardization document describes software architecture as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[The] fundamental concepts or properties of an entity in its environment and governing principles for the realization and evolution of this entity and its related life cycle processes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.iso.org/obp/ui/en/#iso:std:iso-iec-ieee:42010:ed-2:v1:en" rel="noopener noreferrer"&gt;ISO/IEC/IEEE 42010:2022 – Systems and software engineering – Architecture Description&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;“Environment” in that definition is later defined in the same document as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[The] context of surrounding things, conditions, or influences upon an entity&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.iso.org/obp/ui/en/#iso:std:iso-iec-ieee:42010:ed-2:v1:en" rel="noopener noreferrer"&gt;ISO/IEC/IEEE 42010:2022 – Systems and software engineering – Architecture Description&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Personally, I like this definition and I think it serves the purpose of defining architecture well enough for newcomers to the topic. For the purposes of the rest of this article, however, we will only learn about two facets of software architecture: architectural patterns and components, and reusability. These are the most significant and impactful parts of software architecture as well as the easiest to explain. Let’s go over what each one means.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architectural Patterns and Components
&lt;/h3&gt;

&lt;p&gt;Architectural components are layers of functionality within a system that are responsible for a specific system-wide task like accessing a datastore or routing application requests. Architectural patterns refer to the ways in which these different components work together to achieve the system’s purpose.&lt;/p&gt;

&lt;p&gt;The idea of architectural patterns is somewhat similar to that of design patterns; like design patterns, architectural patterns are made up of components accomplishing specific tasks that are pieced together to accomplish broader tasks in the most effective way possible. Another way in which architectural patterns are like design patterns is that there are many well-documented patterns to choose from, each with their own strengths and weaknesses. However, unlike design patterns, architectural patterns have system-wide impacts.&lt;/p&gt;

&lt;p&gt;As an example, consider the factory method design pattern which creates instances of objects based on a given context. This pattern’s components work together to accomplish a very useful task, but outside of that task, it has little—if any—impact throughout the system. While architectural patterns are also made up of multiple components, each with a specific responsibility, the scope of that responsibility is much larger and less specific than those of a design pattern’s responsibility.&lt;/p&gt;

&lt;p&gt;It’s useful to think of the components of an architectural pattern as self-contained collections of code, interfaces, and possibly infrastructure. This is a level of abstraction higher than the idea of components in a design pattern because design pattern components only consist of code. As an example of an architectural component, consider the model-view-controller (MVC) pattern. In this architectural pattern, the model component (more often referred to as the model layer) consists of not only class definitions, but also the underlying datastore—like a database—of the application. It’s important to understand this idea of components at the architectural level because components are what make up architectural patterns and influence their strengths and weaknesses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reusability
&lt;/h3&gt;

&lt;p&gt;On the topic of software architecture, reusability refers to a component’s suitability for handling a specific system-wide task. To use the MVC architecture example again, the architectural component called the controller layer is responsible for handling application routing tasks. Most of the time, MVC is used in web applications, so the controller layer is responsible for handling HTTP/HTTPS requests from browsers, sending them to the appropriate code hosted on a web server, and sending the response back to the browser. Once the controller layer is built, we don’t have to write it again. This means that no matter how many features we have, the controller layer is reusable for handling all the application routing needs of that feature. This saves the development team weeks of time by sparing them the task of writing HTTP routing code every time they want to introduce a new feature into a system.&lt;/p&gt;

&lt;p&gt;By now we should be starting to understand what the concept of software architecture is getting at. Now, let’s talk about why software architecture is worth knowing about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Architecture Matters
&lt;/h2&gt;

&lt;p&gt;Software architecture is the “big picture” of a software system and therefore permeates every aspect of the code. Consider an obvious metaphor: the architecture of a building. The building’s architecture dictates everything about the building that makes it useful; how many people it can hold, where the emergency exits are, how to move from one area to another, the functions of different parts of the building, how future contractors might make upgrades to the building, even how the building affects the environment around it.&lt;/p&gt;

&lt;p&gt;Additionally, a building’s architect has to make decisions about what attributes of the building are most important, which are nice to have, and which are not important at all. For example, an architect may be told to make a building with the primary goal of keeping operational costs low, even if the building isn’t very aesthetically pleasing. In this case, the architect will decide that, even though floor-to-ceiling windows on every floor would make for a very nice-looking building, it would be terrible for operational costs because the sun will heat up the building during the day and the people inside will have to turn up the air conditioner. In this case, the architect will have to opt for smaller windows throughout the building and perhaps even exterior walls of concrete to absorb the heat.&lt;/p&gt;

&lt;p&gt;Likewise, software architecture dictates everything about the system that makes it useful, and software architects have to make decisions that sacrifice one thing for another. In software architecture, these “things” that are sacrificed are called quality attributes, and the decisions about which quality attributes to prioritize are called tradeoffs. Let’s talk about both of these concepts, starting with quality attributes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quality Attributes
&lt;/h3&gt;

&lt;p&gt;Quality attributes are the non-functional attributes of a software system. In this case, an attribute is &lt;em&gt;non-functional&lt;/em&gt; in that it doesn’t do anything. For example, suppose we’re building a calculator app. Being able to do addition is an example of a functional attribute. On the other hand, how quickly the calculator can produce the results of adding two numbers together is a non-functional attribute. Saying the calculator is fast or slow is a comment on one of the calculator’s quality attributes. Aside from the power and modernity of the physical infrastructure upon which a project runs, nothing impacts a system’s quality attributes more than its architecture. Let’s define some of the most important quality attributes, what they are, and how architectural decisions affect them.&lt;/p&gt;

&lt;h4&gt;
  
  
  Reliability
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Reliability&lt;/em&gt;&lt;/strong&gt; is a quality attribute that defines a system’s ability to perform its tasks under some given conditions for some given amount of time. For example, suppose we’re building a web server upon which someone to host their website. Say one of our users has their homepage, &lt;em&gt;index.html&lt;/em&gt;, on our server. We expect that any time someone in the world sends and HTTP request to our server requesting that &lt;em&gt;index.html&lt;/em&gt; file, our server will properly send the page back to that person. Occasionally, due to any number of reasons, our server will fail to send the requested index.html page and will instead send the user a &lt;em&gt;404 – Not Found&lt;/em&gt; response code. This is considered a failure.&lt;/p&gt;

&lt;p&gt;The probability of our server correctly returning the requested &lt;em&gt;index.html&lt;/em&gt; page at any given time under some given condition is a measure of reliability. For example, suppose we send one thousand requests for the &lt;em&gt;index.html&lt;/em&gt; page over the span of fifteen minutes and our server correctly sends back the &lt;em&gt;index.html&lt;/em&gt; page 991 times, the reliability of our server with at one thousand requests over fifteen minutes is thus 99.1%.&lt;/p&gt;

&lt;p&gt;One way in which software architecture affects reliability in this case is how we decide to handle request failures on the server. When the server receives a request for &lt;em&gt;index.html&lt;/em&gt; and for some reason cannot find it, instead of sending back a failure 404 message to the user, we could tell the server to try again up to five times. A very simplified version of how this might look in the code is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def handle_request(file_name, retries=0):
  try:
    resource = open(file_name)
    # File was found, send it to the requester
    send(resource)
  except:
    # File not found, try again
    retries += 1
    if retries &amp;lt; 5:
      print(f"Resource not found, retry number {retries}")
      handle_request(file_name, retries)
    else:
      # Couldn't find file after 5 attempts,
      # send 404 error message
      send(404)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, we wrote a function that handles a request for a resource like &lt;em&gt;index.html&lt;/em&gt; and sends it back to the user (note, the &lt;code&gt;send&lt;/code&gt; method is not defined in this code, this is just for example purposes). We put the &lt;code&gt;open&lt;/code&gt; method inside of a &lt;code&gt;try&lt;/code&gt; block and use the &lt;code&gt;except&lt;/code&gt; block to handle any failure to find the resource. This will help alleviate any random failures that might happen by simply telling the server to try again. However, we also prevent any infinite loops from happening by telling the server to quit trying to find the requested resource after five tries. If the max number of retries is reached, the server sends the 404 response code. Now if we were to test the server again with a thousand requests for &lt;em&gt;index.html&lt;/em&gt;, we may see improvements; perhaps the server eventually sends the requested resource 999 times, increasing our reliability measure to 99.9%.&lt;/p&gt;

&lt;h4&gt;
  
  
  Availability
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Availability&lt;/em&gt;&lt;/strong&gt; is closely related to reliability in that it measures the probability that a system will be available to perform its task at any given time. This measure is directly impacted by the system’s reliability, but also takes things like maintenance downtime into account. Availability over some period of time is measured as that period of time, minus the amount of downtime and then divided by the period of time being measured. For example, if we measure daily availability and find that the system is unavailable for about five minutes every day, the availability of the system is 1440 (the number of minutes in a day) minus 5 (the number of minutes the system is unavailable), all divided by 1440, or 99.65%.&lt;/p&gt;

&lt;p&gt;You may occasionally hear people refer to their system availability in terms of nines. The system in our previous example has “two nines” of availability because the number 99.65 has two nines in it. These numbers are often used in service level agreements (SLAs), contracts that system developers have with their customers agreeing on how much availability they can expect from the system. Five nines (99.999%) of availability is considered very high availability as it allows for five minutes and 15 seconds of downtime a year.&lt;/p&gt;

&lt;p&gt;Software architecture impacts the system’s availability by defining how system maintenance is conducted. For example, if an application’s database goes offline for some reason, can the application still be accessed while we figure out how to get the database back up and running, or does the whole system have to come offline? If we wrote our components to be reliant on the database, the whole application will likely be unavailable while the database is down. If it takes us five minutes and 15 seconds to get the application back online, we can’t have any more downtime for the rest of the year if we want maintain five nines availability.&lt;/p&gt;

&lt;h4&gt;
  
  
  Scalability
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Scalability&lt;/em&gt;&lt;/strong&gt; refers to how a system’s performance and cost increases and decreases with demand. For example, imagine our system has a baseline number of 500 users at any given time, but for some reason, one day we have two-thousand users for a couple of hours. In order for the system to perform identically for all users, we’ve programmed it to spin up a duplicate server every additional 500 users to handle the extra demand. Also, we’ve programmed the system to spin down those servers as the spike in demand tapers off. This means that both cost and performance increase and decrease based on the demands placed on the system.&lt;/p&gt;

&lt;p&gt;Scalable systems are created by writing modular code. As a senior engineer or the architect on your team, you enforce code modularity by ensuring that the components that rely on infrastructure can handle that infrastructure being duplicated. For example, hardcoding the IP address of our servers in the code would not be conducive to scalability since new servers would have different IP addresses.&lt;/p&gt;

&lt;h4&gt;
  
  
  Security
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Security&lt;/em&gt;&lt;/strong&gt; is a quality attribute that refers to a system’s ability to protect data from unauthorized access, prevent users from accessing a higher level of privilege in the system than they need, and much more. Security is a broad topic and there’s a ton of information to know about it, so this section will cover only a very small subset of how it applies to software architecture.&lt;/p&gt;

&lt;p&gt;When you’re architecting a system, you have to think about how data will be stored and if it’s allowed to travel networks unencrypted. For example, when transmitting data from a web server to a user’s browser, the data is accessible to people (network administrators, people using packet sniffers, and so on). In fact, it’s good practice to assume that any data traveling over a network is being read by nefarious people. We might not care who sees some data if it’s something innocuous like a person’s shoe size, but often we transmit data like names or credit card numbers over a network and we definitely don’t want people reading that, so we encrypt it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**_Encryption_**, like security, is also a broad topic but I wanted to briefly define what it is in case you’ve not heard of it before. Basically, encryption is the process of scrambling data so that it’s not human-readable, and the only way to unscramble it is with a special decoder called an encryption key. Generally speaking, only the machine receiving encrypted data has the appropriate encryption key, so even if that data is captured by nefarious people, it is no good to them because they can’t read what it says.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system’s data encryption policy is an important architectural decision because data is much bigger when it’s encrypted than when not. As a consequence, encrypted data takes slightly longer to travel from point a to point b in a network. It’s not a huge difference, but as your system grows, the amount of data flowing through the system will impact the system’s performance. Figuring out what data needs to be encrypted is just one small facet of security minded software architecture.&lt;/p&gt;

&lt;h4&gt;
  
  
  Maintainability
&lt;/h4&gt;

&lt;p&gt;The last quality attribute we’ll discuss is &lt;strong&gt;&lt;em&gt;maintainability&lt;/em&gt;&lt;/strong&gt;. A system’s maintainability is a qualitative measure of how easily developers can add features, fix bugs, or tweak performance. Maintainability isn’t something we can measure with a formula; it is more of a general feeling about how easy the system is to work with from a developer’s perspective. Many of the topics you learn as you become a more senior developer are techniques for writing maintainable code. For example, making smart decisions about class design makes future work easier to do because intuitive class design lowers cognitive complexity. Likewise, using design patterns where appropriate along with naming their components descriptively helps developers navigate the system easily, reducing the time needed to add a new feature or fix an overlooked bug.&lt;/p&gt;

&lt;p&gt;Software architecture impacts the maintainability of the system because every architectural decision influences how code must be written. As an example, a microservices architecture pattern is useful for separating business concerns into individually deployable components. This means that, as a developer, if I get tasked with writing a feature for the marketing team, I know exactly which component I need to work on. However, if I’m working in a system built on the MVC architectural pattern, I may have to work with several components to deliver the required feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architectural Tradeoffs
&lt;/h3&gt;

&lt;p&gt;Now that know what quality attributes are and have seen some examples, let’s talk about &lt;strong&gt;&lt;em&gt;architectural tradeoffs&lt;/em&gt;&lt;/strong&gt;. As a senior developer or software architect, you’ll often be faced with building features that have competing priorities. Consider the example we used when talking about reliability. Adding the &lt;code&gt;try … except&lt;/code&gt; blocks to the server’s code allowed us to increase the server’s reliability, but it most likely will make the server a little slower. This is because exception handling is very slow when exceptions are raised, meaning that every now and then, a user will have a slightly slower experience than if we got rid of the server’s exception handling altogether.&lt;/p&gt;

&lt;p&gt;Deciding which is more important, the speed of the request response or the reliability of the server, is an architectural tradeoff you will have to make. This decision will be influenced by many factors such as the kind of application you’re building, the needs of the users you’re building it for, and much more. There are no universally correct answers to architectural tradeoff questions, they always depend on the context in which you’re working.&lt;/p&gt;

&lt;p&gt;One of the tradeoffs you’ll have to think about quite often is security. As we discussed in the quality attribute section, something like encryption can have a significant impact on your system’s performance. As an architect, you’ll have to decide what needs to be encrypted and what doesn’t. If you’re working in the defense industry, you’ll likely have to encrypt every bit of data that travels over a network, causing your system to perform slowly. However, if you’re writing web-based browser games that don’t require a login, you likely don’t need to encrypt anything. The kinds of tradeoffs you make will depend on the industry in which you’re working and the type of system you’re building.&lt;/p&gt;

&lt;p&gt;One thing that will impact your architectural decisions and tradeoffs is the due date of your projects. For example, if you have a year to build a back-office application for a small company, you will likely have maintainability as a high priority so that you can troubleshoot problems easily and add new features to the system upon request. Conversely, if you’ve been tasked with building the same system in a month, you will not take the time to consider maintainability. This is because building maintainable systems requires extra care and planning, time you don’t have with such a quick due date.&lt;/p&gt;

&lt;p&gt;Yet another decision about architecture you’ll have to make is whether to build a component yourself or use a third-party component. Third party components, sometimes called &lt;strong&gt;&lt;em&gt;commercial off the shelf (COTS)&lt;/em&gt;&lt;/strong&gt; software, are components built by other organizations that you usually have to pay for. COTS software is supposed to require very little work for a developer, and sometimes includes 24-hour support (that is, you can call someone for help if the COTS software isn’t doing what you want it to). One example of a homegrown vs. COTS solution is the decision on how to monitor your system’s performance. Quite often, it’s necessary to watch your system’s performance such as CPU or RAM usage, network latency, and much more. Some teams find it best to write their own software for monitoring system performance while others buy performance monitoring software from other vendors. The decision on which way to go will depend on a lot of things such as staffing (you need more developers to build and maintain such software) and cost (some performance monitoring applications are very expensive), and whether or not the COTS software can easily service your needs.&lt;/p&gt;

&lt;p&gt;Finally, perhaps the most important consideration when making architectural tradeoffs is cost. You and/or your company have a finite amount of money set aside to build whatever system you’re working on. How you use that money to accomplish the goals of the system often includes making several architectural tradeoffs. For example, do you want to pay for a database management system like Microsoft SQL Server so that you can have 24-hour support ready to help you if something goes wrong, or do you prefer using an open-source option like MySQL or Postgres for free, but which do not have a helpdesk for you to call? The answer to that question will depend on many factors. For example, are you a lone developer for the company you’re building this system for, and the company needs the application to be running all the time? If so, you might want to opt for the SQL Server option since you may need help one day. Conversely, are you building an open-source project for people to share recipes with each other? If so, your budget is probably small, and your users won’t lose millions of dollars if your database stops working. In such a case, self-hosting a free database system like MySQL should be fine.&lt;/p&gt;

&lt;p&gt;The responsibility for making the decisions on these tradeoffs will fall on you more often as you become more experienced in whatever tech community you’re a part of, be it an open-source organization or a company. Understanding the overall goals your system and how your organization plans to use and support it will be an important step towards making good architectural tradeoffs.&lt;/p&gt;

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

&lt;p&gt;This article introduced an important concept in your path to becoming an experienced and professional-grade programmer: software architecture. Software architecture can be defined in a number of ways, but it’s ultimately the process of developing components and fitting them together in the most efficient way relevant to our system’s goals. We learned about those components and how they form architectural patterns. Then, we learned about quality attributes and how they’re impacted by software architecture. Learning about quality attributes is a prerequisite to learning about architectural tradeoffs, the decisions you must make when developing systems. Hopefully now you have an understanding for what software architecture is and why it’s important.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How to Debug Code (with Python Examples)</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Mon, 25 Sep 2023 04:01:06 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/how-to-debug-code-with-python-examples-453f</link>
      <guid>https://dev.to/erikwhiting88/how-to-debug-code-with-python-examples-453f</guid>
      <description>&lt;p&gt;Often in your programming career, you will inadvertently write flawed code that introduces some fault into your codebase. These faults are called bugs and the activity of fixing bugs is called “debugging.” Of course, as developers, we try to write correct code every time, but writing bugs is simply a fact of life for programmers. The ability to diagnose and fix bugs is the mark of an experienced and talented developer and is foundational for advanced troubleshooting. In this article, we’ll go over some techniques for effective debugging and introduce you to PDB, the Python debugger. At the end of this article, you’ll be ready to not only troubleshoot and fix your own code, but to diagnose and debug existing code as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fundamentals of Debugging
&lt;/h2&gt;

&lt;p&gt;As a developer, you will spend a lot of time debugging. In fact, several sources estimate that as little as 35% or as much as 75% of a developer’s time is spent debugging code that’s already been written rather than writing new code (&lt;a href="https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.444.9094&amp;amp;rep=rep1&amp;amp;type=pdf" rel="noopener noreferrer"&gt;here’s a pretty good source that puts that number between 35% and 50%&lt;/a&gt;). Since so much of our time as developers will be spent debugging, we should put effort into building this skill. As with all skills, you will get better at debugging the more you do it. There are, however, some fundamental techniques to troubleshooting and debugging software that you should know and build upon. This section will introduce those fundamentals, starting with confirming the bug.&lt;/p&gt;

&lt;h3&gt;
  
  
  Confirm the Bug
&lt;/h3&gt;

&lt;p&gt;An important part of debugging code is understanding the broader context and knowing what the code is intended to do. This is important because your first step in fixing a bug is confirming that it truly is a bug. For example, consider a bug report that says, “the &lt;code&gt;area_of_cube&lt;/code&gt; function isn’t returning the proper values unless you pass it 6.” In order to start debugging, we first decide to try the function out. We load up a console and try a few values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from formulas import area_of_cube
&amp;gt;&amp;gt;&amp;gt; area_of_cube(4)
96
&amp;gt;&amp;gt;&amp;gt; area_of_cube(5)
150
&amp;gt;&amp;gt;&amp;gt; area_of_cube(6)
216
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks right, so we go and double check the formula for finding the surface area of a cube and find that it is the length of an edge squared and then multiplied by six. That means that the numbers we got back from our console test are correct. However, we remember that the bug report says the function only works when you pass it six. Now we wonder if the user reporting the bug is confusing area with volume, since the formula for the volume of a cube is the edge length raised to the third power (or cubed). This means that a cube with edges of length 6 will have both a surface area and volume of 216, and we think the user reporting this bug meant to use the volume function and erroneously reported the area function as having a bug.&lt;/p&gt;

&lt;p&gt;At this point, we have to track down the user reporting the bug and see if they really meant to use the area function when they were reporting the bug or if they meant to use the volume function. This is what confirming the bug is about, making sure a reported bug truly is a bug. This is an important step in debugging because it could potentially save you from fixing code that isn’t actually broken. This example may seem silly, but you will be surprised how often reported bugs in the software are actually due to misuse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reproduce the Bug
&lt;/h3&gt;

&lt;p&gt;Once you’ve confirmed a bug report is genuine, the next step in fixing a bug is reproducing it. Many times, bug reports will say something isn’t working but when you go to check it out yourself, it seems like it’s working fine. In order to properly diagnose the problem, you have to first see the problem happening. As an example, imagine you get a bug report from a coworker that says something like “The &lt;code&gt;greet_user&lt;/code&gt; function isn’t working. The function doesn’t print anything to the console when called.” You start your console to test it out and see no problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from greeters import greet_user
&amp;gt;&amp;gt;&amp;gt; greet_user('Erik')
Good evening, Erik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above console session, you imported the reportedly buggy &lt;code&gt;greet_user&lt;/code&gt; method and called it by passing &lt;code&gt;Erik&lt;/code&gt; as an input parameter. The function then printed “Good evening, Erik” as expected. You haven’t yet reproduced the bug, so now you have to go look at the code and see if you can figure out what’s going on. You open up the &lt;strong&gt;&lt;em&gt;greeters.py&lt;/em&gt;&lt;/strong&gt; file and look for the &lt;code&gt;greet_user&lt;/code&gt; method and see this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import datetime

def greet_user(name):
  now = datetime.datetime.now()
  hour = now.hour
  if hour &amp;lt; 12:
    print(f'Good morning, {name}')
  elif hour &amp;gt; 12 and hour &amp;lt; 18:
    print(f'Good afternoon, {name}')
  elif hour &amp;gt; 18:
    print(f'Good evening, {name}')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you look over this code, you see that the method extracts the hour of the day and prints an appropriate greeting: “good morning” if the hour is before 12, “good evening” if it’s after 12 but before 18, and “good evening” if it’s after 18. The bug report said the function isn’t printing anything, how could that be possible?&lt;/p&gt;

&lt;p&gt;Upon further inspection, you notice that the method’s &lt;code&gt;if&lt;/code&gt; statement only provides instructions for what to do if the &lt;code&gt;hour&lt;/code&gt; variable is 0 to 11, 13 to 17, or 19 to 23. If &lt;code&gt;hour&lt;/code&gt; is 12 or 18, the code does nothing! This means there’s 2 hours of the day in which this code will not print anything to the console. The person who reported the bug must have been trying to use it during one of those times. In order to test your theory, you decide to manually set the &lt;code&gt;hour&lt;/code&gt; variable to 12 to see if that reproduces the bug:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def greet_user(name):
  now = datetime.datetime.now()
  # hour = now.hour
  hour = 12
  if hour &amp;lt; 12:
    print(f'Good morning, {name}')
    . . .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you rerun the same commands from your console session earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from greeters import greet_user
&amp;gt;&amp;gt;&amp;gt; greet_user('Erik')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this time, you don’t see any output. You’ve successfully reproduced the bug and you now know why the bug is happening. In order to fix this bug, we simply have to update the conditionals to use greater-than-or-equal-to comparisons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import datetime

def greet_user(name):
  now = datetime.datetime.now()
  # hour = now.hour
  hour = 12
  if hour &amp;lt; 12:
    print(f'Good morning, {name}')
  elif hour &amp;gt;= 12 and hour &amp;lt; 18:
    print(f'Good afternoon, {name}')
  elif hour &amp;gt;= 18:
    print(f'Good evening, {name}')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, with your &lt;code&gt;now = 12&lt;/code&gt; line still active, you can see that the code now works. This is why reproducing the problem is important, some of the trickiest bugs only show up under specific conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge Assumptions
&lt;/h3&gt;

&lt;p&gt;Another technique for debugging especially tricky bugs is challenging your assumptions. Sometimes, a bug makes no sense and no matter how many things we test, we cannot seem to figure out why a bug is happening. When this happens, the next step is to ask ourselves if the things we generally take for granted still apply. This means making sure environment variables are what you think they are, verifying any authentication functions are still working, making sure you’re using versions of software that support what you’re trying to do, and so on.&lt;/p&gt;

&lt;p&gt;As an example, imagine you receive a bug report saying there’s something wrong with the length_check method; it’s throwing an error any time someone tries to use it. You find the method in your codebase to see it’s defined as the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def length_checker(max, values):
  if (count := len(values)) &amp;gt; max:
    print(f'Cannot have more than {max} values, you have {count}')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method takes two inputs, &lt;code&gt;max&lt;/code&gt; and &lt;code&gt;values&lt;/code&gt;, and prints an error if the number of items in the &lt;code&gt;values&lt;/code&gt; parameter is above the &lt;code&gt;max&lt;/code&gt;. Everything seems to look fine to you, so you start a console session to test the method out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from checkers import length_checker
&amp;gt;&amp;gt;&amp;gt; length_checker(1, [2,2])
Cannot have more than 1 values, you have 2
&amp;gt;&amp;gt;&amp;gt; length_checker(2, [1,2])
&amp;gt;&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, you call &lt;code&gt;length_checker&lt;/code&gt; and pass it a &lt;code&gt;max&lt;/code&gt; value of one and a list with two items. Doing so causes the function to print an error to the console as expected. In the next line, we call &lt;code&gt;length_checker&lt;/code&gt; with a &lt;code&gt;max&lt;/code&gt; value of two and again pass it a two-item list. This time, nothing is printed to the console, as we expected. This function seems to be working perfectly, why did someone report a bug?&lt;/p&gt;

&lt;p&gt;It’s time to challenge our assumptions. The error report came from someone else on a different computer, perhaps there’s some difference between their computer and our own that is causing this function to fail. You decide to start by checking the Python version of your computer and the bug reporter’s. You run &lt;code&gt;python --version&lt;/code&gt; in your command terminal and see that you’re currently using Python 3.10. The bug reporter runs the same command and lets you know they’re using Python 3.7.&lt;/p&gt;

&lt;p&gt;Could the error be because the bug reporter is on an older version of Python than you? You take a closer look at the function and realize that it uses the walrus operator (the &lt;code&gt;:=&lt;/code&gt; syntax). You vaguely remember reading about this being added to Python a few years ago, so you look up when it was added and find out that the walrus operator wasn’t part of Python until Python 3.8! No wonder the function isn’t working for the bug reporter, that version of Python doesn’t even know what to do with the &lt;code&gt;:=&lt;/code&gt; syntax. To fix this bug, you simply ask the reporter to update their Python version to 3.8 or higher, and the problem is solved.&lt;/p&gt;

&lt;p&gt;Challenging your assumptions is one of the easiest steps to forget when it comes to advanced troubleshooting and debugging. Whenever you find yourself working on a bug that doesn’t make sense, ask yourself if you’ve tested literally every facet of the program—from the operating system to the software versions, and every line of code up to and including the error. Doing so will often show you that one of your assumptions is wrong and that’s why you’re encountering the bug.&lt;/p&gt;

&lt;p&gt;Now that we’ve talked about the fundamentals of debugging, it’s time to talk about a built-in Python tool that makes troubleshooting easier: the debugger.&lt;/p&gt;

&lt;h2&gt;
  
  
  PDB: The Python Debugger
&lt;/h2&gt;

&lt;p&gt;The Python debugger (called PDB) is a tool built into the Python programming language that allows us to stop a script at run time so we can check the value of variables at that given moment in the script’s execution. In this section we’ll learn how to set breakpoints, check the value of variables, and step into functions and methods. We’ll start with setting breakpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Breakpoints and Checking Values
&lt;/h3&gt;

&lt;p&gt;When using a debugger, a breakpoint refers to a line in the code upon which we want to pause execution of the program. Before we see how to set a breakpoint with PDB, let’s write a script in which to use the debugger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def add(x, y):
  sum = x + y
  return sum

a = 1
b = 2
c = add(a, b)
print(f"c is {c}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is very simple. First, we define a method called &lt;code&gt;add&lt;/code&gt; which takes two parameters and returns their sum. Then, we create two variables, &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, and a third &lt;code&gt;c&lt;/code&gt; which is the return value of &lt;code&gt;add&lt;/code&gt; when passed &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; variables. Finally, we print the value of &lt;code&gt;c&lt;/code&gt; to the console.&lt;/p&gt;

&lt;p&gt;Now, lets set our first breakpoint to see how using the debugger works. Just above the line &lt;code&gt;a = 1&lt;/code&gt;, write &lt;code&gt;breakpoint()&lt;/code&gt;, and then run the script. You should see the following output in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; path/to/script.py(6)&amp;lt;module&amp;gt;()
-&amp;gt; a = 1
(Pdb)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are three things to note in the output above. First, the line preceded with the &lt;code&gt;&amp;gt;&lt;/code&gt; symbol is telling us what file we’re in (your output may vary depending on what you named this file and where you saved it). The next line, &lt;code&gt;-&amp;gt; a = 1&lt;/code&gt;, shows us where in the Python script we’ve stopped. Notice that this is the line just below where we set our breakpoint. The line &lt;code&gt;a = 1&lt;/code&gt; hasn’t run yet, we’ve paused the script just before its execution. Finally, you see &lt;code&gt;(Pdb)&lt;/code&gt; and a prompt. We can type debugger commands in this prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; You don’t also write &lt;code&gt;import pdb; pdb.set_trace()&lt;/code&gt; instead of &lt;code&gt;breakpoint()&lt;/code&gt;, but this is considered the “old way”. In fact, if you’re using Python 3.7 or below (which you shouldn’t because they’re all deprecated), you’ll have to use this. When I first wrote this article, I was using the &lt;code&gt;set_trace&lt;/code&gt; way exlusively, so if you see one in the article, it’s because I missed it and you can easily just drop in &lt;code&gt;breakpoint()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first command we’ll run is &lt;code&gt;next&lt;/code&gt;, type &lt;code&gt;next&lt;/code&gt; into the console and press enter. You should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; path/to/script.py(7)&amp;lt;module&amp;gt;()
-&amp;gt; b = 2
(Pdb)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we’re on the next line of the script. The &lt;code&gt;next&lt;/code&gt; command executes the line in which we were paused and then pauses on the next line. So, when we typed &lt;code&gt;next&lt;/code&gt; just now, Python ran the line &lt;code&gt;a = 1&lt;/code&gt; and stopped on the line you see in the console now, &lt;code&gt;b = 2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One of the main benefits of using the debugger is seeing the value of variables at a given time. Since we’re paused just after the &lt;code&gt;a = 1&lt;/code&gt; line, we can type the variable name a into the debugger console and see what the value is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(Pdb) print(a)
1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful for when we want to confirm that a variable holds the value we think it does. If we want, we can also change the value of a here as well, check it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(Pdb) a = 5
(Pdb) print(a)
5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manually setting variable values at runtime like this is helpful for experimenting when debugging; sometimes you want to see how different values will cause a script to behave.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; If you have a variable that happens to share a name with a debugger command, you can prefix the variable name with an exclamation mark (&lt;code&gt;!&lt;/code&gt;) to have the word interpreted as the script variable instead of the debugger command.&lt;/p&gt;

&lt;p&gt;Now, let’s stop pausing the script and allow it to finish running. We do this with the &lt;code&gt;continue&lt;/code&gt; command which will let the program run until it reaches the next breakpoint or until it’s done executing. Run &lt;code&gt;continue&lt;/code&gt; and you should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(Pdb) continue
c is 7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice two things here. First, the output says &lt;code&gt;c is 7&lt;/code&gt;. This is because when we paused the script, we set the value of &lt;code&gt;a&lt;/code&gt; to 5, so when we passed &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; to the &lt;code&gt;add&lt;/code&gt; function, we actually passed 5 and 2 instead of 1 and 2 like the script appears to say. Also notice that your console is probably back to your normal command prompt instead of the debugger. This is because the script has finished executing.&lt;/p&gt;

&lt;p&gt;Now that we know how to set breakpoints, move around in a script, check the value of a variable at a given time, and change the value of a variable, lets look at stepping into functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stepping Into Functions
&lt;/h3&gt;

&lt;p&gt;When we set a breakpoint in a script, the debugger does not leave the scope of where it’s pausing the script. As an example, move your breakpoint from the previous section to just over the &lt;code&gt;c = add(a, b)&lt;/code&gt; line. Now, run the script, you should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; path/to/script.py(8)&amp;lt;module&amp;gt;()
-&amp;gt; c = add(a, b)
(Pdb)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the debugger is paused just before the &lt;code&gt;add&lt;/code&gt; function is called. Type &lt;code&gt;next&lt;/code&gt; and hit enter in the debugger console, you should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; path/to/script.py(9)&amp;lt;module&amp;gt;()
-&amp;gt; print(f"c is {c}")
(Pdb)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the debugger paused at the next line after the function call instead of going into the &lt;code&gt;add&lt;/code&gt; function itself like we might expect. This is because the default behavior of the debugger is to step over function calls so that you, as the developer, can stay inside of the context in which you’re debugging. If you want to step into a function, you have to use the &lt;code&gt;step&lt;/code&gt; command. Run the script again, once you get here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; path/to/script.py(8)&amp;lt;module&amp;gt;()
-&amp;gt; c = add(a, b)
(Pdb)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type step and then press enter. Now, you’ll be in the &lt;code&gt;add&lt;/code&gt; function and you should see the following in your console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--Call--
&amp;gt; path/to/script.py(1)add()
-&amp;gt; def add(x, y):
(Pdb)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice a couple of new things about the debugger’s output now. First, at the top of the output is a line that says &lt;code&gt;--Call--&lt;/code&gt;, this lets us know that we’ve left the context in which we were originally debugging because a function or method call was made. Also notice that the line containing the file location no longer says &lt;code&gt;&amp;lt;module&amp;gt;&lt;/code&gt; but says &lt;code&gt;add()&lt;/code&gt;. Again, this lets you know that you are currently debugging a function inside of the script.&lt;/p&gt;

&lt;p&gt;Now you know how to use the debugger to move around a script, check and change values of variables, and step into functions. These operations exist in virtually every programming language debugger out there, so the commands you learned in this chapter will likely be the same or similar for any other debugger you might use in the future.&lt;/p&gt;

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

&lt;p&gt;In this article you learned the foundational skills of debugging software. We started by learning about three important steps to debugging: confirming the bug, reproducing it, and challenging your assumptions. Then, we learned about PDB, Python’s built-in debugging tool. We learned how to pause a script at run time so we can check the values of variables, then we learned how to control a script’s execution with the next and continue commands. Finally, we learned how to step into functions while debugging with the step command. All of these skills will serve you well in your future work as a programmer and will go a long way in advanced troubleshooting.&lt;/p&gt;

&lt;p&gt;If you liked this article about debugging, you may like my &lt;a href="https://erikscode.space/index.php/2023/09/16/test-driven-development-with-python-a-primer/" rel="noopener noreferrer"&gt;primer on TDD with Python&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>python</category>
    </item>
    <item>
      <title>Python Exception Handling and Customization</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Sun, 17 Sep 2023 23:47:05 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/python-exception-handling-and-customization-33j7</link>
      <guid>https://dev.to/erikwhiting88/python-exception-handling-and-customization-33j7</guid>
      <description>&lt;p&gt;Like bugs, exceptions are inevitable when developing software, especially as the complexity of that software increases. Sometimes exceptions are surprising, other times we can anticipate them coming. How a program responds to the occurrence of exceptions is called exception handling, and as programmers, we can define and customize exception handling. In this chapter, we’ll learn what exceptions are, how to handle them, and how to make our own.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Exceptions?
&lt;/h2&gt;

&lt;p&gt;Exceptions can be thought of as unplanned events in the execution of a program that disrupt that execution. When a runtime error occurs, a specific exception is raised. If an exception is raised and the program does not have any code defining how to handle that exception, the exception is said to be uncaught, and it will terminate execution of the program. Exceptions are not unique to Python; every programming language has exceptions and a means of handling them. You’ve actually most likely seen lots of exceptions already, but just for clarity, let’s raise a few exceptions on purpose.&lt;/p&gt;

&lt;p&gt;First, in a Python console, try to divide any number by zero and press enter. You should see something similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print(3 / 0)
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
ZeroDivisionError: division by zero
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we tried to divide by zero, Python raised an exception. In this case, the exception raised was &lt;code&gt;ZeroDivisionError&lt;/code&gt;. &lt;code&gt;ZeroDivisionError&lt;/code&gt; is the name of the exception raised when a program tries to divide by zero. There are other kinds of exceptions as well, let’s raise another. In the Python console, try to add a number to a string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print('hi' + 2)
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
TypeError: can only concatenate str (not "int") to str
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, Python raised a &lt;code&gt;TypeError&lt;/code&gt;. &lt;code&gt;TypeError&lt;/code&gt; is the kind of exception raised when a program tries to do something to an object that the object’s class doesn’t support. Notice also that there’s a message along with the exception: &lt;code&gt;can only concatenate str (not “in”) to str&lt;/code&gt;. Exceptions can, and often do, have different messages for different ways in which they can be raised. For example, let’s raise another &lt;code&gt;TypeError&lt;/code&gt;, this time by trying to divide a number by a string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print(20 / 'hi')
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
TypeError: unsupported operand type(s) for /: 'int' and 'str'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, Python raises a &lt;code&gt;TypeError&lt;/code&gt; in this situation, but notice that the message is different. The message says &lt;code&gt;unsupported operand type(s) for /: ‘int’ and ‘str’&lt;/code&gt;. This will be relevant later when we write our own exceptions.&lt;/p&gt;

&lt;p&gt;Now that we have an intuition about what exceptions are, lets learn how to handle them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Exceptions
&lt;/h2&gt;

&lt;p&gt;An exception will terminate the execution of a program if left unhandled. For example, consider the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this script, we have a method called &lt;code&gt;divide&lt;/code&gt; that takes two parameters, divides them, and returns the result. Next, we have three lines calling the &lt;code&gt;divide&lt;/code&gt; function and printing the result. Notice that the second line passes zero as a second parameter; let’s see what happens when we try to run this script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2.0
Traceback (most recent call last):
  File "path/to/script.py", line 5, in &amp;lt;module&amp;gt;
    print(divide(2, 0))
  File "path/to/script.py", line 2, in divide
    return x / y
ZeroDivisionError: division by zero
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the program printed 2.0 to the console, meaning the first call to the &lt;code&gt;divide&lt;/code&gt; function worked. Then, the program raised an exception, &lt;code&gt;ZeroDivisionError&lt;/code&gt;, on the second line because we tried to divide by zero. Notice also that the program did not run the final line, &lt;code&gt;print(divide(9, 3))&lt;/code&gt;. This is because the &lt;code&gt;ZeroDivisionError&lt;/code&gt; was an uncaught exception. In order to make the program continue running, we have to write code specifically for handling that exception. We do this in Python with &lt;code&gt;try except&lt;/code&gt; blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using try and except
&lt;/h3&gt;

&lt;p&gt;In Python, we use the keywords &lt;code&gt;try&lt;/code&gt; and &lt;code&gt;except&lt;/code&gt; to handle exceptions. The &lt;code&gt;try&lt;/code&gt; block contains the operation that may raise an exception, and the &lt;code&gt;except&lt;/code&gt; block contains the code that defines what we want the program to do when an exception is raised. As an example, let’s rewrite the &lt;code&gt;divide&lt;/code&gt; function from earlier to handle &lt;code&gt;ZeroDivisionError&lt;/code&gt; exceptions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ZeroDivisionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot divide by zero&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the line &lt;code&gt;return x / y&lt;/code&gt; is now in a &lt;code&gt;try&lt;/code&gt; block. This tells Python to run the code in this block until the last line, or until an exception is raised. If an exception is raised, Python checks for an &lt;code&gt;except&lt;/code&gt; block that matches the type of exception. In our case, we wrote except &lt;code&gt;ZeroDivisionError&lt;/code&gt;, so if a &lt;code&gt;ZeroDivisionError&lt;/code&gt; is raised, Python will run the code inside of the &lt;code&gt;except&lt;/code&gt; block. To see this is action, run the script with the updated &lt;code&gt;divide&lt;/code&gt; function. You should see the following output in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2.0
Cannot divide by zero
3.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, when the script got to the line that said &lt;code&gt;print(divide(2, 0))&lt;/code&gt;, the program did not print the exception message to the console, it instead ran the code in the &lt;code&gt;except&lt;/code&gt; block, which we can see in the console when it printed &lt;code&gt;Cannot divide by zero&lt;/code&gt;. Notice also that even though an exception was raised, the program continued execution, as we can see by the 3.0 printed to the console when Python ran the last line of our script. This is an example of how exception handling is useful, we can anticipate problems and handle them without terminating the program.&lt;/p&gt;

&lt;p&gt;Note: When a program encounters an error or otherwise fails in some way but does not terminate its execution, it is said to fail &lt;em&gt;gracefully&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Other Types of Exceptions
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;divide&lt;/code&gt; function can now fail gracefully when a &lt;code&gt;ZeroDivisionError&lt;/code&gt; exception is raised, but what about other exceptions? What if someone tries to pass a string to the function? As an example, update the last lines in the previous script to look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hi&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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 try to run the script now, you’ll see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2.0
Cannot divide by zero
Traceback (most recent call last):
  File "path/to/script.py", line 14, in &amp;lt;module&amp;gt;
    print(divide('hi', 2))
  File "path/to/script.py", line 7, in divide
    return x / y
TypeError: unsupported operand type(s) for /: 'str' and 'int'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice this time that Python raised a &lt;code&gt;TypeError&lt;/code&gt; when we tried to divide a string with an integer. We never wrote any code to handle this exception, so Python terminated the program once this exception was raised. If we want to add code to handle this exception, we have two options.&lt;/p&gt;

&lt;p&gt;First, we could add another &lt;code&gt;except&lt;/code&gt; block to the &lt;code&gt;divide&lt;/code&gt; function for that specific exception. The function would then look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ZeroDivisionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot divide by zero&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Can only divide number types&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would handle both &lt;code&gt;ZeroDivisionError&lt;/code&gt; and &lt;code&gt;TypeError&lt;/code&gt; exceptions. But there are yet more exceptions, we cannot anticipate them all. Instead of writing an &lt;code&gt;except&lt;/code&gt; block for each exception type that could possibly beraised, we can write an &lt;code&gt;except&lt;/code&gt; block that catches all exceptions besides the &lt;code&gt;ZeroDivisionError&lt;/code&gt; one. This approach would have the function looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ZeroDivisionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot divide by zero&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An error occurred&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the &lt;code&gt;divide&lt;/code&gt; function written this way, there is no exception that can be raised which would terminate execution of our program. We have an &lt;code&gt;except&lt;/code&gt; block dedicated specifically to catching &lt;code&gt;ZeroDivisionError&lt;/code&gt; exceptions and informing the user they cannot divide by zero, and we have an &lt;code&gt;except&lt;/code&gt; block that catches any other kind of exception that could possibly be raised and simply alerts the user that an error occurred. These are the basics of handling exceptions in Python but there’s one more thing to learn about, finally blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using finally
&lt;/h3&gt;

&lt;p&gt;When a line of code raises an exception, Python immediately leaves that line and goes to the except block (or terminates the program) meaning that nothing under the line raising the exception gets executed. To get an idea why this is a problem, consider the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Add function completed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An error occurred&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hi&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we’ve defined an &lt;code&gt;add&lt;/code&gt; function that tries to add its parameters together and print the result to the console, then prints that it has completed. An &lt;code&gt;except&lt;/code&gt; block catches any exceptions and prints that an error has occurred. Under the function we call the function twice, once with numbers and once with a string and a number, forcing an exception. Let’s see what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;6
Add function completed
An error occurred
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that when the exception was raised, we didn’t see &lt;code&gt;Add function completed&lt;/code&gt; printed to the console. This is because once the error was raised, the Python interpreter left the &lt;code&gt;try&lt;/code&gt; block and went to the &lt;code&gt;except&lt;/code&gt; block, leaving the &lt;code&gt;print&lt;/code&gt; statement unexecuted. If we want to execute code regardless of if an error is raised or not, we have to use a &lt;code&gt;finally&lt;/code&gt; block. The &lt;code&gt;finally&lt;/code&gt; keyword is used like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An error occurred&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Add function completed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve added a &lt;code&gt;finally&lt;/code&gt; block and put the line printing &lt;code&gt;Add function completed&lt;/code&gt; in it. This will ensure that this line runs every time the function is called, regardless of whether there is a caught exception. Run the script again and you should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;6
Add function completed
An error occurred
Add function completed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, the message &lt;code&gt;Add function completed&lt;/code&gt; prints to the console every time. This is how &lt;code&gt;finally&lt;/code&gt; blocks work.&lt;/p&gt;

&lt;p&gt;Now we know how to handle exceptions with &lt;code&gt;try&lt;/code&gt;, &lt;code&gt;except&lt;/code&gt;, and &lt;code&gt;finally&lt;/code&gt;. There is one other thing you should know about exception handling before we move on to customized exceptions. Handling exceptions is computationally slow. This is for a variety of reasons that are much too technical to be relevant to this chapter. The main point is that using exception handling to handle errors may be slower than other techniques (like &lt;code&gt;if&lt;/code&gt; statements). Exception handling is best used when we don’t want errors to terminate program execution. Otherwise, it’s often better to use &lt;code&gt;if&lt;/code&gt; statements or to just let the program execution terminate. With that caution out of the way, lets talk about customized exceptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customized Exceptions
&lt;/h2&gt;

&lt;p&gt;In the previous sections, we raised two different types of exceptions, &lt;code&gt;ZeroDivisionError&lt;/code&gt; and &lt;code&gt;TypeError&lt;/code&gt;. These exception classes are just two of many other built-in exception classes in Python. Other exception classes include &lt;code&gt;ImportError&lt;/code&gt;, &lt;code&gt;ModuleNotFoundError&lt;/code&gt;, &lt;code&gt;KeyError&lt;/code&gt;, and many more. In addition to these built-in exception classes, we can also make our own custom exception classes. Customizing exception classes is useful in large projects because it aids in debugging, and it helps you define how errors are handled in your system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Custom Exception Class
&lt;/h3&gt;

&lt;p&gt;To create a customized exception, we simply write a class that inherits Python’s &lt;code&gt;Exception&lt;/code&gt; class. Write the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, writing a custom exception is just a matter of making a subclass of &lt;code&gt;Exception&lt;/code&gt;. Now, to raise this exception, we use the raise keyword. Consider the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;MyError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this script, we make a simple loop that prints its iteration number but raises our customized &lt;code&gt;MyError&lt;/code&gt; exception if the number is 3. If you run this script, you should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1
2
3
Traceback (most recent call last):
  File "path/to/script.py", line 8, in &amp;lt;module&amp;gt;
    raise MyError
__main__.MyError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that in the output, we see that our custom exception was raised. Suppose we did not know about this script but found a bug report saying “some method is throwing a &lt;code&gt;MyError&lt;/code&gt; exception.” Since this is a custom (that is, non-built-in) exception class, we can search our codebase for any line that says &lt;code&gt;raise MyError&lt;/code&gt; and figure out what’s going on. When developing large and complex software systems, saving time by searching for customized exceptions is very helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Editing the Exception Message
&lt;/h3&gt;

&lt;p&gt;We can further customize our exception classes by overriding their constructor methods and defining what message they print to the console. For example, suppose we are writing a human resources application for tracking employee salaries. We might have an &lt;code&gt;Employee&lt;/code&gt; class like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have a basic &lt;code&gt;Employee&lt;/code&gt; class that takes a &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;salary&lt;/code&gt; attribute in its constructor. Now suppose we wanted to ensure that an employee’s salary is between 20 thousand and 500 thousand and we want to not only raise an exception when someone attempts to make an Employee object with a &lt;code&gt;salary&lt;/code&gt; attribute outside of that range, we also want to log such an event to a database. First, we have to create a custom exception, we’ll call it &lt;code&gt;SalaryError&lt;/code&gt;. Then, we’ll override its constructor to print why an exception was raised and to log the exception to a database. Check it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SalaryError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Salary must be between 20k and 500k, you put &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Logging the following to the database:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Attempted to create employee with salary &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, we create a new class called &lt;code&gt;SalaryError&lt;/code&gt; and inherit the &lt;code&gt;Exception&lt;/code&gt; class, creating a custom exception. Then, we override the constructor by telling it to expect an input called &lt;code&gt;salary&lt;/code&gt;. Then, we set the exception message to inform that a salary attribute must be between 20,000 and 500,000 and put what the attempted salary was.&lt;/p&gt;

&lt;p&gt;Next, we print that we are logging the error to the database (in this example, we don’t actually log anything to a database since setting up the necessary connections for that would take away from the focus of this article). Finally, we use &lt;code&gt;super()&lt;/code&gt; to fill out the base &lt;code&gt;Exception&lt;/code&gt; class’s information so that the class will behave as a standard Python exception.&lt;/p&gt;

&lt;p&gt;In order to implement this exception, we’ll tweak the &lt;code&gt;Employee&lt;/code&gt; constructor to raise the exception if the &lt;code&gt;salary&lt;/code&gt; attribute falls out of the desired range:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20000&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;500000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;     &lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SalaryError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;salary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we’ve rewritten the &lt;code&gt;Employee&lt;/code&gt; constructor to check if the &lt;code&gt;salary&lt;/code&gt; range is within the 20 to 500 thousand range. If it is, we continue with constructing the object; if not, we raise the &lt;code&gt;SalaryError&lt;/code&gt; exception. To see how this works, write the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code tries to instantiate an &lt;code&gt;Employee&lt;/code&gt; object with a &lt;code&gt;salary&lt;/code&gt; of 19,000, just below the required range. If you try to run this code, you should see the following output in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Logging the following to the database:
Attempted to create employee with salary 19000
Traceback (most recent call last):
  File "path/to/script.py", line 16, in &amp;lt;module&amp;gt;
    bob = Employee('Bob', 19000)
  File "path/to/script.py", line 11, in __init__
    raise SalaryError(salary)
__main__.SalaryError: Salary must be between 20k and 500k, you put 19000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see here that the &lt;code&gt;Employee&lt;/code&gt; constructor raised the &lt;code&gt;SalaryError&lt;/code&gt; exception and printed out the appropriate error message. It also alerts the user that the error is being logged to the database.&lt;/p&gt;

&lt;p&gt;This is the benefit of writing custom exceptions. Not only do we help our future debugging efforts by making exceptions searchable, we also can craft descriptive and helpful error messages. Additionally, custom exceptions let us specify the behavior of our program when encountering errors, allowing us to do things like report errors to a database.&lt;/p&gt;

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

&lt;p&gt;In this article, we improved our debugging and quality assurance skills by learning about exceptions and exception handling in Python. We started by learning about handling exceptions, allowing us to define how the occurrence of certain errors affect the behavior of our programs. Then, we learned how to write our own custom exceptions and how doing so can improve our future troubleshooting efforts. These skills come in handy especially as your software system grows in complexity and usage, since this typically leads to interesting program states that need to be specifically handled.&lt;/p&gt;

&lt;p&gt;For more Python-specific information on exceptions, check out &lt;a href="https://docs.python.org/3/tutorial/errors.html" rel="noopener noreferrer"&gt;chapter 8 in the Python docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’re trying to get better at Python, try one of my other language-specific tutorials like the delegation/decorator pattern series starting here: &lt;a href="https://erikscode.space/index.php/2020/08/01/delegate-and-decorate-in-python-part-1-the-delegation-pattern/" rel="noopener noreferrer"&gt;Delegate and Decorate in Python: Part 1 – The Delegation Pattern&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>Test-Driven Development with Python: a Primer</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Sat, 16 Sep 2023 21:12:05 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/test-driven-development-with-python-a-primer-5f46</link>
      <guid>https://dev.to/erikwhiting88/test-driven-development-with-python-a-primer-5f46</guid>
      <description>&lt;p&gt;Making sure the software we build works the way we (and our customers) want it to work is called, unsurprisingly, software testing. Software testing is an enormous topic; indeed, there are entire books, courses, conferences, academic journals, and more about the topic. One can even make a career out of testing software. We couldn’t possibly scratch the surface of the complexity involved in software testing in this article, so we’ll only focus on a topic most relevant to us as programmers: test-driven development.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Test-Driven Development?
&lt;/h2&gt;

&lt;p&gt;To put it simply, test-driven development, or &lt;em&gt;TDD&lt;/em&gt;, is a programming style in which a component’s tests are the primary mechanism guiding its development–this is often accomplished by writing tests &lt;strong&gt;&lt;em&gt;before&lt;/em&gt;&lt;/strong&gt; writing feature code. This is in contrast to the way software is traditionally built, where a feature is built end-to-end and then testing is added later as an afterthought.&lt;/p&gt;

&lt;p&gt;There are several reasons for taking a test-first approach to building software. Most importantly, it forces you to think before you start writing code. Pondering how you might test something you’ve not written yet will necessarily make you imagine how you intend to build it, what you want it to do, and how other parts of the code might interact with it. Writing tests first also helps flush out unanswered questions you hadn’t yet thought about (for example, should a math function gracefully handle bad datatype inputs or fail loudly? What kind of data should a function expect as input? And so on).&lt;/p&gt;

&lt;p&gt;One practical reason for writing tests before application code is that after a while, you have a fairly comprehensive test suite that reports on the functionality of most—if not all—of your system. This is a lifesaver as your projects get more complex and the possibility of a minor change in one part of the code breaking a feature in another area increases.&lt;/p&gt;

&lt;p&gt;Now you may be wondering what it means to “write” a test. In the context of TDD, the word test is almost always shorthand for unit test—a program that checks the functionality of one small piece of functionality (a unit). If that sounds like it means we write code to test code, it’s because we do! In Python, unit tests are classes and methods that we build in order to verify the performance of other classes and methods that we build. Let’s first learn how to write unit tests before diving in to the TDD workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Unit Testing in Python
&lt;/h2&gt;

&lt;p&gt;As their name suggests, unit tests test one unit of code—that could be a function’s return value, the attributes of a class, or even a single unit of functionality like the ability to login to a website. We don’t have to get hung up on the semantics right now, let’s just start writing. Create a file called &lt;em&gt;add_fucntion.py&lt;/em&gt; and write this function in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above function simply takes two arguments and returns their sum (adds them together). Now, suppose we wanted to test this function to make sure it works. We might open an interactive Python shell and make sure it returns the values we expect based on the values we pass to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from add_function import add
&amp;gt;&amp;gt;&amp;gt; add(5, 5)
10
&amp;gt;&amp;gt;&amp;gt; add(4, -2)
2
&amp;gt;&amp;gt;&amp;gt; add(True, "hello")
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
  File "path/to/add_function.py", line 2, in add
    return x + y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above session, we imported the &lt;code&gt;add&lt;/code&gt; function from &lt;code&gt;add_function&lt;/code&gt;. We passed 5 and 5 to the function to see if we got 10 as expected; we pass a 4 and a -2 to make sure the function handles signed and unsigned integers appropriately; and finally, we pass the Boolean &lt;code&gt;True&lt;/code&gt; and string &lt;code&gt;hello&lt;/code&gt; to the function to make sure it throws an error. All inputs behave as expected, so we can be pretty sure the &lt;code&gt;add&lt;/code&gt; function behaves as expected.&lt;/p&gt;

&lt;p&gt;This is fine for this function since it’s small and simple, but what if we have much larger functions or functions that change a lot? Are we going to manually test every function in a Python shell like this? As you might expect, the answer is no!&lt;/p&gt;

&lt;p&gt;This is where unit testing comes in, we’ll write a program that will run all these different lines and more. Python has two popular testing frameworks: &lt;code&gt;pytest&lt;/code&gt; and &lt;code&gt;unittest&lt;/code&gt;. The &lt;code&gt;unittest&lt;/code&gt; module is part of the standard library, meaning we don’t have to do anything special to install it, so we’ll use it for the examples in this chapter.&lt;/p&gt;

&lt;p&gt;To get started with &lt;code&gt;unittest&lt;/code&gt;, make a file in the same directory as &lt;em&gt;add_function.py&lt;/em&gt; and call it &lt;em&gt;test_add_function.py&lt;/em&gt;. Inside this new file we first need to import the &lt;code&gt;unittest&lt;/code&gt; module and the file with the &lt;code&gt;add&lt;/code&gt; function in it. To do that, make the top of the &lt;em&gt;test_add_function.py&lt;/em&gt; file look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;add_function&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, with the &lt;code&gt;add&lt;/code&gt; function and &lt;code&gt;unittest&lt;/code&gt; module imported, it’s time to write our first test. With &lt;code&gt;unittest&lt;/code&gt;, we start by first defining a test class. Test classes are usually a collection of tests for one conceptual level of functionality; in this case, the &lt;code&gt;add&lt;/code&gt; function. Let’s call ours &lt;code&gt;AddTest&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the test class inherits the &lt;code&gt;TestCase&lt;/code&gt; class from &lt;code&gt;unittest&lt;/code&gt;. This gives us access to the &lt;code&gt;assert&lt;/code&gt; methods we’ll use in a few minutes. Next, we’ll define a test method. Test methods are what make up test classes and we usually write one for each of the different ways our code might be used. For example, the most likely use of our add function is probably to add positive numbers, so let’s write a test method for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_positive_addition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, all we did was add the test method &lt;code&gt;test_positive_addition&lt;/code&gt; to the &lt;code&gt;AddTest&lt;/code&gt; test class. Now we’re ready to write the actual assertions. In this case, we’ll pass the &lt;code&gt;add&lt;/code&gt; function two numbers, save its return value in a variable called &lt;code&gt;actual&lt;/code&gt;, and compare that with a variable called &lt;code&gt;expected&lt;/code&gt; (the number that should be returned). Then, we’ll use the &lt;code&gt;assertEqual&lt;/code&gt; method from &lt;code&gt;unittest&lt;/code&gt; to test that the two values are the same. Here’s how your entire &lt;code&gt;test_add_funciton.py&lt;/code&gt; file should like by now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;add_function&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_positive_addition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice inside of the test method &lt;code&gt;test_positive_addition&lt;/code&gt; we create two variables, &lt;code&gt;expected&lt;/code&gt; with the value of 30, and &lt;code&gt;actual&lt;/code&gt; with the return value of &lt;code&gt;add&lt;/code&gt; when passed 10 and 20. Finally, we call the &lt;code&gt;assertEqual&lt;/code&gt; class method and pass it &lt;code&gt;actual&lt;/code&gt; and &lt;code&gt;expected&lt;/code&gt;. As you might guess from its name, this method checks if the two values passed to it are equal.&lt;/p&gt;

&lt;p&gt;You’ve now written your first unit test! It’s time to actually run the test. Open a terminal and, from whatever folder your &lt;code&gt;add_function.py&lt;/code&gt;and &lt;code&gt;test_add_function.py&lt;/code&gt; files are in, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m unittest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs the &lt;code&gt;unittest&lt;/code&gt; program which will find any file that starts with the word test and runs the assertions inside. You should see output similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
----------------------------------------------------------------------
Ran 1 test in 0.000s

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

&lt;/div&gt;



&lt;p&gt;You might not see it, but the single dot at the top of the terminal output represents a test method that passed. Had the test failed, you would have seen an F. This segues nicely into an important point: you should always make sure your tests can fail. We actually never saw our test fail so how can we be 100% certain that our unit test is working?&lt;/p&gt;

&lt;p&gt;To make sure our unit test is working the way we expect, let’s change the &lt;code&gt;expected&lt;/code&gt; variable to 40 and see what happens. Make this change in your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run &lt;code&gt;python -m unittest&lt;/code&gt; in your console once again. You should see something like the following output:&lt;br&gt;
&lt;/p&gt;

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

==================================================================

FAIL: test_positive_addition (test_add_function.AddTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/path/to/test_add_function.py", line 9, in test_positive_addition
    self.assertEqual(actual, expected)

AssertionError: 30 != 40
----------------------------------------------------------------------

Ran 1 test in 0.001s
FAILED (failures=1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very interesting output, not only do we see that our test is testing the right thing (which we can see by the FAILED message when we tried to see if 20 + 10 could equal 40), but we also see what it looks like when a test fails. Notice that the output includes the file name and test method that failed as well as the line number of the assertion that caused the failure. This is super helpful when running big test suites (collections of automated tests like this one) with hundreds or thousands of tests.&lt;/p&gt;

&lt;p&gt;Notice too that the failure message also tells us what failed. Specifically, it tells us that 30 != 40, which is exactly what we put into the test to force a failure. Go ahead and change the &lt;code&gt;expected&lt;/code&gt; variable back to 30.&lt;/p&gt;

&lt;p&gt;Now that we know how to write unit tests, let’s write a couple more. First, let’s test the method’s ability to handle negative numbers. We’ll also write this test specifically to fail. Check it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_negative_addition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we’ve defined another test method under the &lt;code&gt;AddTest&lt;/code&gt; test class. This time, we are using negative numbers to see if the add function handles numbers lower than zero. We’ll test this by passing 10 and -20 to the add function, but instead of setting the &lt;code&gt;expected&lt;/code&gt; variable to -10, we set it to 0. We do this because we want to make sure the unit test we just wrote is testing the right thing, and the best way to do that is by forcing an assertion failure. Once again, go ahead and run &lt;code&gt;python -m unittest&lt;/code&gt; in your terminal, you should see something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;F.

==================================================================
FAIL: test_negative_addition (test_add_function.AddTest)
----------------------------------------------------------------------

Traceback (most recent call last):
  File "path/to/test_add_function.py", line 14, in test_negative_addition
    self.assertEqual(actual, expected)

AssertionError: -10 != 0
----------------------------------------------------------------------

Ran 2 tests in 0.001s
FAILED (failures=1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice this time that the first line of output has a . followed by an F. This means that one of the test methods failed while another passed. As we hoped, the rest of the output tells us that our &lt;code&gt;test_negative_addition&lt;/code&gt; method failed because -10 does not equal 0. Go ahead and change the &lt;code&gt;expected&lt;/code&gt; variable to -10 so that the tests will pass.&lt;/p&gt;

&lt;p&gt;Let’s write a slightly different test now. In the previous examples, we asserted two values were equal. This is of course an important kind of test to run but that’s not the only thing functions ever do. Remember earlier we tested what would happen by calling the &lt;code&gt;add&lt;/code&gt; function by passing it &lt;code&gt;True&lt;/code&gt; and the string hello and we saw that it raised a &lt;code&gt;TypeError&lt;/code&gt;? We can actually test for that behavior too, check it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_bad_datatypes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;     &lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above test method, we start by using the &lt;code&gt;with&lt;/code&gt; keyword in combination with the &lt;code&gt;unittest&lt;/code&gt; assert method &lt;code&gt;assertRaises&lt;/code&gt; and pass it &lt;code&gt;TypeError&lt;/code&gt;. Finally, inside the &lt;code&gt;with&lt;/code&gt; block, we call the &lt;code&gt;add&lt;/code&gt; function and pass &lt;code&gt;True&lt;/code&gt; and the string hello. We have to use the &lt;code&gt;with&lt;/code&gt; block because otherwise the method will error (even though it’s the error we’re testing for).&lt;/p&gt;

&lt;p&gt;If you run this, it should pass. For the sake of time, I did not show you how to make this test intentionally fail. I leave that as an exercise to the reader.&lt;/p&gt;

&lt;p&gt;Aside from &lt;code&gt;assertTrue&lt;/code&gt; and &lt;code&gt;assertRaises&lt;/code&gt;, &lt;code&gt;unittest&lt;/code&gt; has many other assertion methods such as &lt;code&gt;assertAlmostEqual&lt;/code&gt; for approximating, &lt;code&gt;assertIn&lt;/code&gt; for checking the presence of a single element in a list, &lt;code&gt;assertFalse&lt;/code&gt; for checking things you expect to be untrue, and many more.&lt;/p&gt;

&lt;p&gt;Now that we’ve learned the basics of writing unit tests in Python with &lt;code&gt;unittest&lt;/code&gt;, let’s talk about the flow of TDD.&lt;/p&gt;

&lt;h2&gt;
  
  
  The TDD Flow
&lt;/h2&gt;

&lt;p&gt;As I mentioned at the beginning of this article, test-driven development often consists of writing tests before writing actual code, but that’s just the beginning. The TDD workflow follows a three-phase cycle: write a failing test, write just enough code to make that test pass, refactor. You repeat this cycle until the code is doing what it’s meant to do, is thoroughly tested, and is as well designed as it can be. To understand the TDD workflow, we’ll start with analyzing the requirements and then repeating the cycle a couple of times.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Requirements
&lt;/h3&gt;

&lt;p&gt;Imagine we are building a cash register application for our favorite coffee shop. This application currently consists of a &lt;code&gt;Drink&lt;/code&gt; class, representing the many different drinks the coffee shop serves, an &lt;code&gt;Order&lt;/code&gt; class that records a customer’s orders, and an &lt;code&gt;OrderItem&lt;/code&gt; class representing an individual item in an order. These three simple classes are in a file called &lt;em&gt;coffee_cash_register.py&lt;/em&gt; and look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Drink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above class hierarchy consists of a &lt;code&gt;Drink&lt;/code&gt; class which contains just a constructor and &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;price&lt;/code&gt; attributes, an &lt;code&gt;OrderItem&lt;/code&gt; class which simply contains a &lt;code&gt;drink&lt;/code&gt; attribute, and an &lt;code&gt;Order&lt;/code&gt; class that contains a list of &lt;code&gt;OrderItem&lt;/code&gt; instances and a method for adding more &lt;code&gt;OrderItem&lt;/code&gt; objects to that list.&lt;/p&gt;

&lt;p&gt;We now want to build a class called &lt;code&gt;CashRegister&lt;/code&gt; that serves as an way to access the &lt;code&gt;Order&lt;/code&gt; class and allows an employee to create orders and build receipts. Since we are doing this the TDD way, our first step is to write a failing test for the &lt;code&gt;CashRegister&lt;/code&gt; class.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write a Failing Test
&lt;/h3&gt;

&lt;p&gt;To write our first test for &lt;code&gt;CashRegister&lt;/code&gt;, we first have to think about what kind of attributes and features the &lt;code&gt;CashRegister&lt;/code&gt; class should have. Let’s start by thinking about what a real-world cash register does. It allows an employee to build an order by adding items a customer wants to purchase or removing items if one was accidentally added to the order. It should also be able to calculate the total price for the entire order, so the employee knows how much to charge the customer.&lt;/p&gt;

&lt;p&gt;This thought process has revealed three things the &lt;code&gt;CashRegister&lt;/code&gt; class must be able to do, and thus three test methods. Create a file called &lt;em&gt;test_cash_register.py&lt;/em&gt; and write the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;coffee_cash_register&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CashRegisterTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CashRegister&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_remove_item_from_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CashRegister&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_calculate_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CashRegister&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now remember, you want to write just enough of the test that the test should fail. We currently have three test methods, each creating a new instance of the &lt;code&gt;CashRegister&lt;/code&gt; class—a class we haven’t even created yet. Run &lt;code&gt;python -m unittest&lt;/code&gt; in the directory you’ve created these files and see that you have three failures with messages like &lt;code&gt;name CashRegister is not defined&lt;/code&gt;. We’ve successfully completed the first part of our TDD cycle, writing a failing test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get the Test to Pass
&lt;/h3&gt;

&lt;p&gt;Now that we have our test class and three test methods created and failing, it’s time to get them to pass. Since our tests failed because &lt;code&gt;CashRegister&lt;/code&gt; wasn’t defined, let’s go ahead and create that class. In &lt;em&gt;coffee_cash_register.py&lt;/em&gt;, add the following class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CashRegister&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we’ve created the &lt;code&gt;CashRegister&lt;/code&gt; class with a very basic constructor. If you run the tests again, you’ll see that they pass. Believe it or not, that means we’re actually done with the second part of the TDD cycle: getting the test to pass. Let’s move on to the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refactor
&lt;/h3&gt;

&lt;p&gt;Before we return to the start of the TDD cycle, we need to refactor the code we’ve written. This includes both the test code and the application code; but right at this moment in our particular example, the only thing that needs refactoring is our test code. Notice how we instantiated a &lt;code&gt;CashRegister&lt;/code&gt; object at the beginning of each test method. In order to save us from retyping the same line for every test method, let’s just make &lt;code&gt;cr&lt;/code&gt; a class attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CashRegisterTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;cr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CashRegister&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_remove_item_from_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_calculate_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we defined an attribute for the test class called &lt;code&gt;cr&lt;/code&gt; and instantiated it with &lt;code&gt;CashRegister()&lt;/code&gt;. Now we don’t have to write this line at the beginning of every test method. Notice also that we replaced the line inside each test method with &lt;code&gt;pass&lt;/code&gt;, this is simply because since we no longer need to instantiate a &lt;code&gt;CashRegister&lt;/code&gt; object, there is nothing to write in the test methods. If we leave them empty, our subsequent test runs will fail.&lt;/p&gt;

&lt;p&gt;Now, let’s repeat the TDD cycle a couple more times to really get a feel for how this works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repeat
&lt;/h3&gt;

&lt;p&gt;We’ve now completed one iteration of the TDD cycle. The next step is to write another failing test. Actually, we’ll just add to one of our existing tests and get it to fail. Let’s write the test code for the test method &lt;code&gt;test_add_item_to_order&lt;/code&gt;. Again, we have to start by thinking about how this might work. We decide that adding an item to an order will most likely be done by creating a method in &lt;code&gt;CashRegister&lt;/code&gt; that takes an instance of &lt;code&gt;Drink&lt;/code&gt;, turns it into an &lt;code&gt;OrderItem&lt;/code&gt;, and adds it to an &lt;code&gt;Order&lt;/code&gt; object’s &lt;code&gt;items&lt;/code&gt; attribute. We write the test method as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Drink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Latte&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.49&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we run the tests, we should see a failure from this test method because the &lt;code&gt;CashRegister&lt;/code&gt; object has no attribute &lt;code&gt;add_item_to_order&lt;/code&gt;. The next step in the cycle is to get the test to pass, which right now means building that method for the &lt;code&gt;CashRegister&lt;/code&gt; class. We might start by writing a method in &lt;code&gt;CashRegister&lt;/code&gt; that would look something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But now that we’ve written this line and are wondering how to add it to an order, we realize that neither the method nor the class actually has an &lt;code&gt;Order&lt;/code&gt; object to add the &lt;code&gt;OrderItem&lt;/code&gt; to. Now we have to think about how we plan to instantiate the idea of an Order into our &lt;code&gt;CashRegister&lt;/code&gt; app. Do we make it a class attribute of the &lt;code&gt;CashRegister&lt;/code&gt; class? Do we make &lt;code&gt;CashRegister&lt;/code&gt; inherit &lt;code&gt;Order&lt;/code&gt;? Neither of these approaches sound quite right since a cash register in real life is mostly independent from the orders it builds. We decide instead to pass an instance of &lt;code&gt;Order&lt;/code&gt; to the &lt;code&gt;add_item_to_order&lt;/code&gt; method. Check it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the method above, we’ve updated the argument list to take in an &lt;code&gt;order&lt;/code&gt; parameter—an instance of the &lt;code&gt;Order&lt;/code&gt; class. This will allow us to add the &lt;code&gt;OrderItem&lt;/code&gt; instance to an actual &lt;code&gt;Order&lt;/code&gt; instance. We also need to update our test code to account for the new method parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Drink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Latte&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.49&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we’ve instantiated an empty &lt;code&gt;Order&lt;/code&gt; object, we can call the &lt;code&gt;add_item_to_order&lt;/code&gt; method without breaking anything. This means we’ve completed the “get test to pass” portion of the TDD cycle once again! The next step should be to refactor the code but, in this case, there is not really much to refactor, so we start the cycle over once again.&lt;/p&gt;

&lt;p&gt;We’re now starting iteration three of the TDD cycle and once again, our first task is to get the test to fail. The best way to accomplish that at this point is to write our first assertion. Since the &lt;code&gt;add_item_to_order&lt;/code&gt; method is supposed to add an &lt;code&gt;Item&lt;/code&gt; object to an &lt;code&gt;Order&lt;/code&gt; object’s &lt;code&gt;items&lt;/code&gt; attribute, and since we are instantiating an &lt;code&gt;Order&lt;/code&gt; object with an empty &lt;code&gt;items&lt;/code&gt; attribute in our test, we can assert that this method is working as intended by checking that the length of &lt;code&gt;order.items&lt;/code&gt; is greater than 0. Check it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Drink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Latte&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.49&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the line we added, &lt;code&gt;self.assertTrue(len(order.items) &amp;gt; 0)&lt;/code&gt;. We figure if the &lt;code&gt;add_item_to_order&lt;/code&gt; method is working like it should, the &lt;code&gt;order.items&lt;/code&gt; list will have one item in it. If we run this test, it should fail with a message like &lt;code&gt;False is not True&lt;/code&gt;. This fails because, in our application code, we never add the &lt;code&gt;OrderItem&lt;/code&gt; object to the &lt;code&gt;Order&lt;/code&gt; object’s items attribute. We’re again done with the first part of the TDD cycle. Let’s complete the second part of the TDD cycle by fixing the &lt;code&gt;add_item_to_order&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We make this test pass by adding a call to the &lt;code&gt;Order&lt;/code&gt; object’s &lt;code&gt;add_item&lt;/code&gt; method which adds the &lt;code&gt;item&lt;/code&gt; variable to the &lt;code&gt;order&lt;/code&gt; variable’s &lt;code&gt;items&lt;/code&gt; attribute. If you run the tests again, you should see that this one now passes. It’s time for the refactor stage.&lt;/p&gt;

&lt;p&gt;Now that we think about it, the test we wrote is a little weak. The length of the &lt;code&gt;order&lt;/code&gt; variable’s &lt;code&gt;items&lt;/code&gt; attribute is only a side effect of what we really wanted to do which was add a &lt;code&gt;LineItem&lt;/code&gt; containing the &lt;code&gt;drink&lt;/code&gt; variable to the &lt;code&gt;order&lt;/code&gt; variable’s &lt;code&gt;items&lt;/code&gt; attribute. By only testing the length of &lt;code&gt;items&lt;/code&gt;, the &lt;code&gt;add_item_to_order&lt;/code&gt; method could add anything at all to the &lt;code&gt;items&lt;/code&gt; attribute and our test would say that it’s passing. For the refactor stage, let’s be a bit more explicit about what we’re testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Drink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Latte&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.49&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_item_to_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertIsInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;   &lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drink&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve rewritten the test method to be more explicit. First, we extract the first object out of the &lt;code&gt;order&lt;/code&gt; variable’s &lt;code&gt;items&lt;/code&gt; attribute after calling the &lt;code&gt;add_item_to_order&lt;/code&gt; method. We expect that the item should be an &lt;code&gt;OrderItem&lt;/code&gt; object, so we use the &lt;code&gt;unittest&lt;/code&gt;&lt;code&gt;assertIsInstance&lt;/code&gt; method to make sure it is. Then, we use the &lt;code&gt;assertEqual&lt;/code&gt; method to make sure that the &lt;code&gt;item&lt;/code&gt; variable’s &lt;code&gt;drink&lt;/code&gt; attribute is the &lt;code&gt;Drink&lt;/code&gt; instance we created earlier in the test. This is a much more explicit test of the functionality we want because not only will it tell us if the method incorrectly created the &lt;code&gt;OrderItem&lt;/code&gt;, it will let us know if we somehow accidentally appended the wrong kind of object to the &lt;code&gt;Order&lt;/code&gt; instance’s &lt;code&gt;items&lt;/code&gt; list.&lt;/p&gt;

&lt;p&gt;It looks like this part of the class is pretty thoroughly tested now and we’re confident that the &lt;code&gt;CashRegister&lt;/code&gt; class’s &lt;code&gt;add_item_to_order&lt;/code&gt; method works as expected. You’ve now completed your first TDD workflow! Practice your understanding of this flow by repeating the steps for the other two test methods. I’ll give you a hint, to write a failing test for &lt;code&gt;test_remove_item_from_order&lt;/code&gt;, you’ll probably have to call a method you haven’t written yet.&lt;/p&gt;

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

&lt;p&gt;This article gently introduces the world of software testing by exploring the concept of test-driven development (TDD). We started by defining what TDD is and why it’s helpful. We highlighted the fact that TDD not only helps us think about the software we build, but it also has the side effect of leaving us with a collection of tests that we can always check our software against. Then, we took a quick detour to talk about how to use Python’s &lt;code&gt;unittest&lt;/code&gt; testing framework so we could learn what it means to “write” tests. We did this so we could practice the TDD workflow with an example. In our example we ran through the TDD cycle three times to fully build out one thorough test method for our &lt;code&gt;CashRegister&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;To learn more about TDD, I suggest you start trying to use the flow in your daily programming work. At first, you will likely be less productive than you are used to, but as you practice more, you may be more productive than you’ve ever been! If you are primarily a Python programmer, I suggest you install &lt;code&gt;pytest&lt;/code&gt; and learn how to use that instead of &lt;code&gt;unittest&lt;/code&gt;. The &lt;code&gt;pytest&lt;/code&gt; package is much more popular in Python projects, we started with &lt;code&gt;unittest&lt;/code&gt; so we could skip the tedium of installing a new package.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding INNER, OUTER, LEFT, and RIGHT Joins in SQL</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Mon, 08 Aug 2022 22:53:59 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/understanding-inner-outer-left-and-right-joins-in-sql-19o9</link>
      <guid>https://dev.to/erikwhiting88/understanding-inner-outer-left-and-right-joins-in-sql-19o9</guid>
      <description>&lt;p&gt;One of the first and most common things newcomers to SQL struggle with is how each &lt;code&gt;JOIN&lt;/code&gt; is different from the other. In this article, I’ll explain the differences between the inner vs outer &lt;code&gt;JOIN&lt;/code&gt; and left vs right &lt;code&gt;JOIN&lt;/code&gt; in SQL using examples from each.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to Joining Tables
&lt;/h2&gt;

&lt;p&gt;In SQL, we use &lt;code&gt;JOIN&lt;/code&gt; in our queries to create result sets made up of multiple tables. For example, it’s common to have &lt;code&gt;countries&lt;/code&gt; and &lt;code&gt;states&lt;/code&gt; tables when capturing address information, so an address record may look something like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;street_address&lt;/code&gt; &lt;code&gt;city&lt;/code&gt; &lt;code&gt;state_or_province&lt;/code&gt; &lt;code&gt;country_id&lt;/code&gt;&lt;br&gt;
123 Main St Houston Texas 1&lt;br&gt;
558 Maple AveToronto Ontario 2&lt;/p&gt;

&lt;p&gt;Here, the numbers in the &lt;code&gt;country_id&lt;/code&gt; column of the &lt;code&gt;addresses&lt;/code&gt; table refer to the IDs of their respective country in the &lt;code&gt;countries&lt;/code&gt; table, which may look like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;id&lt;/code&gt; &lt;code&gt;country_name&lt;/code&gt;&lt;br&gt;
1 United States&lt;br&gt;
2 Canada&lt;/p&gt;

&lt;p&gt;Now, say we want to write a query that displays a full address, something like &lt;em&gt;123 Main St, Houston, TX United States&lt;/em&gt;. Since the street, city, and state names are recorded in the &lt;code&gt;addresses&lt;/code&gt; table, and the country name is recorded in the &lt;code&gt;countries&lt;/code&gt; table, we have to &lt;em&gt;join&lt;/em&gt; the two tables to get the result set that we want. The relevant SQL would probably look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
    a.street_address,
    a.city,
    a.state_or_province,
    c.country_name
FROM
    addresses a
JOIN
    countries c
ON
    a.country_id = c.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SQL code above shows us something like the following results:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;street_address&lt;/code&gt; &lt;code&gt;city&lt;/code&gt; &lt;code&gt;state_or_province&lt;/code&gt; &lt;code&gt;country_name&lt;/code&gt;&lt;br&gt;
123 Main St HoustonTexas United States&lt;br&gt;
558 Maple Ave Toronto Ontario Canada&lt;/p&gt;

&lt;p&gt;Notice here that we have values from the &lt;code&gt;street_address&lt;/code&gt;, &lt;code&gt;city&lt;/code&gt;, and &lt;code&gt;state_or_province&lt;/code&gt; columns of the &lt;code&gt;addresses&lt;/code&gt; table, and values from the &lt;code&gt;country_name&lt;/code&gt; column of the &lt;code&gt;countries&lt;/code&gt; table. We were able to &lt;code&gt;join&lt;/code&gt; these two tables together by matching the &lt;code&gt;country_id&lt;/code&gt; value in &lt;code&gt;addresses&lt;/code&gt; with the &lt;code&gt;id&lt;/code&gt; column of &lt;code&gt;countries&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are a few kinds of &lt;code&gt;join&lt;/code&gt;s in SQL, each one behaving slightly differently. This article aims to help you understand the difference between the different kinds of joins in SQL.&lt;/p&gt;
&lt;h2&gt;
  
  
  Download and Build the Sample Database
&lt;/h2&gt;

&lt;p&gt;If you’d like to follow along with this article, go ahead and clone the &lt;a href="https://github.com/erik-whiting/joins_article" rel="noopener noreferrer"&gt;code to build the example database&lt;/a&gt; . To build the database in pgAdmin, first run the command in &lt;code&gt;create_database.sql&lt;/code&gt; then make sure to change connections to the newly created &lt;code&gt;employee_database&lt;/code&gt; database and run the commands in &lt;code&gt;build_and_seed_tables.sql&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You should now have a database with four tables: &lt;code&gt;addresses&lt;/code&gt;, &lt;code&gt;countries&lt;/code&gt;, &lt;code&gt;departments&lt;/code&gt;, and &lt;code&gt;employees&lt;/code&gt;. Let’s quickly discuss the data model before moving on to the actual point of this article.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;addresses&lt;/code&gt; and &lt;code&gt;countries&lt;/code&gt; tables are just like the ones in the examples above; each address record references a country record. Then, we have an &lt;code&gt;employees&lt;/code&gt; table, each record of which references an address record as well as a department record. The department records are pretty simple; the &lt;code&gt;departments&lt;/code&gt; table simply has an &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;name&lt;/code&gt; column and refers to what department an employee works.&lt;/p&gt;

&lt;p&gt;Ok, now on to actual joins!&lt;/p&gt;
&lt;h2&gt;
  
  
  Right vs. Left Joins
&lt;/h2&gt;

&lt;p&gt;Let’s start by talking about the difference left and right joins. It’s helpful to think about all the tables in a SQL query as a horizontal list of tables. The leftmost table is the table in the &lt;code&gt;FROM&lt;/code&gt; clause, the next table to the right of the leftmost table is whatever table we are joining. So for example, if we write the query&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM employees e JOIN addresses a ON e.address_id = a.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the &lt;code&gt;employees&lt;/code&gt; table is the leftmost table while the &lt;code&gt;addresses&lt;/code&gt; table is the next one to the right, kind of like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwj0zfta5z00zddkobt9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwj0zfta5z00zddkobt9k.png" alt="two rounded squares in a horizontal row, the left square is labeled " width="800" height="225"&gt;&lt;/a&gt;&lt;br&gt;
If we take it a step further and join the &lt;code&gt;countries&lt;/code&gt; table to the &lt;code&gt;addresses&lt;/code&gt;, the next table to the right would be &lt;code&gt;countries&lt;/code&gt;. In other words, the following SQL query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT *
FROM employees e
JOIN addresses a ON e.address_id = a.id
JOIN countries c ON a.country_id = c.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be visualized as the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fip6iv40p77x08dlogar0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fip6iv40p77x08dlogar0.png" alt="three rounded squares in a horizontal row, the left square is labeled " width="800" height="140"&gt;&lt;/a&gt;Notice again that whenever a table is joined to another, the already-existing table (for lack of a better word) is the left table and the joining table is the right table. So in our example above, our base table is &lt;code&gt;employees&lt;/code&gt; so it’s on the left; then we joined &lt;code&gt;addresses&lt;/code&gt; to it, so it’s to the right of &lt;code&gt;employees&lt;/code&gt;. Finally, we then joined &lt;code&gt;countries&lt;/code&gt; to &lt;code&gt;addresses&lt;/code&gt;, putting &lt;code&gt;addresses&lt;/code&gt; to the right of &lt;code&gt;countries&lt;/code&gt; and thus the rightmost table.&lt;/p&gt;

&lt;p&gt;This visualization is helpful in understanding how left and right joins work. For example, query all of the &lt;code&gt;employees&lt;/code&gt; records and &lt;code&gt;LEFT JOIN&lt;/code&gt; the &lt;code&gt;addresses&lt;/code&gt; table and see what happens. The query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT e.first_name, a.street_address, a.city
FROM employees e
LEFT JOIN addresses a ON e.address_id = a.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Bob" "123 Main St" "Houston"
"Jordan" "220 C 30" "Izamal"
"Nicole" "3030 Burgos" "Xalapa"
"Erik" "1010 2nd St" "Omaha"
"Lina" "1010 2nd St" "Omaha"
"Sandra", NULL, NULL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice here that all records for &lt;code&gt;employees&lt;/code&gt;, the leftmost table, appear as results in this query, including a record with no associated &lt;code&gt;addresses&lt;/code&gt; record. The records in the rightmost table, &lt;code&gt;addresses&lt;/code&gt;, only appear if they can be joined to the leftmost table. There are records in &lt;code&gt;addresses&lt;/code&gt; that cannot be joined to &lt;code&gt;employees&lt;/code&gt; because no &lt;code&gt;employees&lt;/code&gt; record has a corresponding &lt;code&gt;address_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Conversely, if we use &lt;code&gt;RIGHT JOIN&lt;/code&gt; to join the &lt;code&gt;addresses&lt;/code&gt; table, we will see results that include all of the &lt;code&gt;addresses&lt;/code&gt; table–the rightmost table–despite not being able to be joined to the &lt;code&gt;employees&lt;/code&gt; table. For example, the query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT e.first_name, a.street_address, a.city
FROM employees e
RIGHT JOIN addresses a ON e.address_id = a.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Bob" "123 Main St" "Houston"
"Jordan" "220 C 30" "Izamal"
"Nicole" "3030 Burgos" "Xalapa"
"Erik" "1010 2nd St" "Omaha"
"Lina" "1010 2nd St" "Omaha"
null "558 Maple Ave" "Toronto"
null "99 Jackson Rd" "Flin Flon"
null "821 Carol" "Nuuk"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice this time that we have three &lt;code&gt;addresses&lt;/code&gt; records in the result set that have &lt;code&gt;null&lt;/code&gt; values in their respective &lt;code&gt;addresses&lt;/code&gt; column. Also notice that the employee record with no associated address record is not in this result set. This is because by doing a &lt;code&gt;RIGHT JOIN&lt;/code&gt;, we essentially tell the database to give us all results of the rightmost table, and join only the leftmost table’s records if they are associated with the rightmost.&lt;/p&gt;

&lt;p&gt;Conversely, we can switch which table is right and left by referring to the &lt;code&gt;addresses&lt;/code&gt; table in the &lt;code&gt;FROM&lt;/code&gt; clause and then joining the &lt;code&gt;employees&lt;/code&gt; table. For example, let’s &lt;code&gt;SELECT&lt;/code&gt; from &lt;code&gt;addresses&lt;/code&gt; and &lt;code&gt;LEFT JOIN&lt;/code&gt; the &lt;code&gt;employees&lt;/code&gt; table. The query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT e.first_name, a.street_address, a.city
FROM addresses a
LEFT JOIN employees e ON e.address_id = a.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Bob" "123 Main St" "Houston"
"Jordan" "220 C 30" "Izamal"
"Nicole" "3030 Burgos" "Xalapa"
"Erik" "1010 2nd St" "Omaha"
"Lina" "1010 2nd St" "Omaha"
null "558 Maple Ave" "Toronto"
null "99 Jackson Rd" "Flin Flon"
null "821 Carol" "Nuuk"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results when we &lt;code&gt;LEFT JOIN&lt;/code&gt; the &lt;code&gt;employees&lt;/code&gt; table to the &lt;code&gt;addresses&lt;/code&gt; table are the same as when we &lt;code&gt;RIGHT JOIN&lt;/code&gt; the &lt;code&gt;addresses&lt;/code&gt; table to the &lt;code&gt;employees&lt;/code&gt; table. That’s because in this case, the leftmost table is &lt;code&gt;addresses&lt;/code&gt; so by left joining the &lt;code&gt;employees&lt;/code&gt; table to it, we are telling the database to give us all the &lt;code&gt;addresses&lt;/code&gt; records and then join the &lt;code&gt;employees&lt;/code&gt; table records if they exist.&lt;/p&gt;

&lt;p&gt;Now, let’s take it a step further and see what happens when we chain &lt;code&gt;JOIN&lt;/code&gt; commands together. First, let’s &lt;code&gt;SELECT FROM&lt;/code&gt; the &lt;code&gt;addresses&lt;/code&gt; table and &lt;code&gt;RIGHT JOIN&lt;/code&gt; the &lt;code&gt;countries&lt;/code&gt; table so we can see how many of the &lt;code&gt;countries&lt;/code&gt; records are not associated to &lt;code&gt;addresses&lt;/code&gt;. The query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
    a.street_address,
    a.city,
    a.state_or_province,
    c.country_name
FROM addresses a
RIGHT JOIN countries c
ON a.country_id = c.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"1010 2nd St"   "Omaha" "NE"    "United States"
"123 Main St"   "Houston"   "TX"    "United States"
"3030 Burgos"   "Xalapa"    "Ver"   "Mexico"
"220 C 30"  "Izamal"    "Yuc"   "Mexico"
"99 Jackson Rd" "Flin Flon" "MB"    "Canada"
"558 Maple Ave" "Toronto"   "ON"    "Canada"
"821 Carol" "Nuuk"  "SQ"    "Greenland"
NULL    NULL    NULL    "Iceland"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see from the result set of our previous query, the only country in our database that isn’t related to an address record is Iceland.&lt;/p&gt;

&lt;p&gt;Knowing this, let’s see what happens when we &lt;code&gt;SELECT FROM&lt;/code&gt; the &lt;code&gt;employees&lt;/code&gt; table, &lt;code&gt;LEFT JOIN&lt;/code&gt; the &lt;code&gt;addresses&lt;/code&gt; table to it, and then &lt;code&gt;RIGHT JOIN&lt;/code&gt; the &lt;code&gt;countries&lt;/code&gt; table to that. Do you think we’ll see all the countries? Let’s find out! The query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
    e.first_name,
    e.last_name,
    a.street_address,
    a.city,
    a.state_or_province,
    c.country_name
FROM employees e
LEFT JOIN addresses a
ON e.address_id = a.id
RIGHT JOIN countries c
ON a.country_id = c.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Lina"  "Mazin" "1010 2nd St"   "Omaha" "NE"    "United States"
"Erik"  "Whiting"   "1010 2nd St"   "Omaha" "NE"    "United States"
"Bob"   "Robertson" "123 Main St"   "Houston"   "TX"    "United States"
"Nicole"    "Nicholson" "3030 Burgos"   "Xalapa"    "Ver"   "Mexico"
"Jordan"    "Mays"  "220 C 30"  "Izamal"    "Yuc"   "Mexico"
NULL    NULL    NULL    NULL    NULL    "Canada"
NULL    NULL    NULL    NULL    NULL    "Greenland"
NULL    NULL    NULL    NULL    NULL    "Iceland"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are interesting results that show us something about the way &lt;code&gt;RIGHT&lt;/code&gt; and &lt;code&gt;LEFT&lt;/code&gt; joins behave. Notice that we only get 5 rows of results that include records from the &lt;code&gt;addresses&lt;/code&gt; table even though there are 7 records in that table. This is because there are only 5 &lt;code&gt;addresses&lt;/code&gt; that are associated to &lt;code&gt;employees&lt;/code&gt; records, and when we &lt;code&gt;LEFT JOIN&lt;/code&gt;ed the &lt;code&gt;addresses&lt;/code&gt; table, we told the database that we only want records from the &lt;code&gt;addresses&lt;/code&gt; table if they’re associated with an employee record. However, when we &lt;code&gt;RIGHT JOIN&lt;/code&gt; the &lt;code&gt;countries&lt;/code&gt; table, we tell the database we want all records from the &lt;code&gt;countries&lt;/code&gt; table, even if there’s no associated &lt;code&gt;addresses&lt;/code&gt; record in the result set.&lt;/p&gt;

&lt;p&gt;Now that we’ve talked all about the difference between &lt;code&gt;RIGHT&lt;/code&gt; and &lt;code&gt;LEFT&lt;/code&gt;, let’s talk about &lt;code&gt;INNER&lt;/code&gt; and &lt;code&gt;OUTER&lt;/code&gt; joins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inner vs. Outer Joins
&lt;/h2&gt;

&lt;p&gt;The difference between &lt;code&gt;INNER&lt;/code&gt; and &lt;code&gt;OUTER&lt;/code&gt; joins are very similar to the differences between &lt;code&gt;LEFT&lt;/code&gt; and &lt;code&gt;RIGHT&lt;/code&gt; joins. However, in this case, it’s more helpful to think of tables as Venn diagrams. You know, the ones where two circles meet in the middle and the overlapping section is some shared attribute between the circles?&lt;/p&gt;

&lt;p&gt;We still want to think of tables being joined from left to right, but with &lt;code&gt;INNER&lt;/code&gt; joins, we have to think about how records might overlap.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: The default JOIN operation in Postgres (and every other RDBMS I've ever worked with) is the INNER JOIN. That means if you write something like SELECT * FROM A JOIN B ON A.b_id = B.id, it is implied that you mean to do an inner join and the SQL SELECT * FROM A INNER JOIN B ON A.b_id = B.id is exactly the same thing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s see how &lt;code&gt;INNER JOIN&lt;/code&gt; works when we join &lt;code&gt;addresses&lt;/code&gt; to &lt;code&gt;employees&lt;/code&gt;. The query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT e.first_name, a.street_address
FROM employees e
INNER JOIN addresses a
ON e.address_id = a.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Bob"   "123 Main St"
"Jordan"    "220 C 30"
"Nicole"    "3030 Burgos"
"Erik"  "1010 2nd St"
"Lina"  "1010 2nd St"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice this time that we have five results, despite there being six &lt;code&gt;employees&lt;/code&gt; records in the database. This is unlike the &lt;code&gt;LEFT JOIN&lt;/code&gt; from the previous section where the employee record with no associated address record was still in the result set. In this way, &lt;code&gt;INNER JOIN&lt;/code&gt; means we only want results from the leftmost table if the rightmost table can be joined to them. That’s why you often see Venn diagrams used to explain joins. In this case, &lt;code&gt;INNER JOIN&lt;/code&gt; is this Venn diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffs009wpakyohxwqy7tjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffs009wpakyohxwqy7tjo.png" alt="a Venn diagram with " width="800" height="527"&gt;&lt;/a&gt;So, the main difference between &lt;code&gt;LEFT&lt;/code&gt; and &lt;code&gt;INNER&lt;/code&gt; joining that we’ve seen so far is that if you want all records of the leftmost table–whether they have associated records in the rightmost table or not–you want to use a &lt;code&gt;LEFT&lt;/code&gt; join. If you only want records from the leftmost table if a record from the right most table can be joined to it, you want to use &lt;code&gt;INNER JOIN&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So what about &lt;code&gt;OUTER&lt;/code&gt;? The &lt;code&gt;OUTER JOIN&lt;/code&gt; is a special case because even though it seems antimonious with &lt;code&gt;INNER JOIN&lt;/code&gt;, &lt;code&gt;OUTER&lt;/code&gt; joins need to to be specified with either &lt;code&gt;RIGHT&lt;/code&gt;, &lt;code&gt;LEFT&lt;/code&gt;, or &lt;code&gt;FULL&lt;/code&gt;. For example, the following SQL will result in a syntax error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- Doesn't work!
SELECT e.first_name
FROM employees e
OUTER JOIN addresses a
ON e.address_id = a.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to specify if we want the leftmost or right most table to be outer-joined. Let’s see how &lt;code&gt;LEFT OUTER JOIN&lt;/code&gt; behaves. The SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
    e.first_name,
    a.street_address
FROM employees e
LEFT OUTER JOIN addresses a
ON e.address_id = a.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Bob"   "123 Main St"
"Jordan"    "220 C 30"
"Nicole"    "3030 Burgos"
"Erik"  "1010 2nd St"
"Lina"  "1010 2nd St"
"Sandra"    NULL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we specified that we want the leftmost table to be outer-joined and therefore got all results from &lt;code&gt;employees&lt;/code&gt; regardless of whether a record from the &lt;code&gt;addresses&lt;/code&gt; table can be joined to it or not.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;RIGHT OUTER JOIN&lt;/code&gt; on the other hand will include all records from the rightmost table regardless of whether a record from the leftmost table can be joined to it. The SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
    e.first_name,
    a.street_address
FROM employees e
RIGHT OUTER JOIN addresses a
ON e.address_id = a.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Bob"   "123 Main St"
"Jordan"    "220 C 30"
"Nicole"    "3030 Burgos"
"Erik"  "1010 2nd St"
"Lina"  "1010 2nd St"
NULL    "558 Maple Ave"
NULL    "99 Jackson Rd"
NULL    "821 Carol"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See here that all the &lt;code&gt;addresses&lt;/code&gt; records were included in the result set, even if there was no &lt;code&gt;employees&lt;/code&gt; record that could be joined to it. Notice also that the value from &lt;code&gt;employees&lt;/code&gt; that has no associated &lt;code&gt;addresses&lt;/code&gt; record is &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; included in the result set.&lt;/p&gt;

&lt;p&gt;Did you notice that the results for &lt;code&gt;LEFT OUTER JOIN&lt;/code&gt; and &lt;code&gt;RIGHT OUTER JOIN&lt;/code&gt; are the exact same results we get from &lt;code&gt;LEFT JOIN&lt;/code&gt; and &lt;code&gt;RIGHT JOIN&lt;/code&gt; respectively? If so, good on you! &lt;code&gt;LEFT JOIN&lt;/code&gt; and &lt;code&gt;LEFT OUTER JOIN&lt;/code&gt; are exactly the same thing; same with &lt;code&gt;RIGHT JOIN&lt;/code&gt; and &lt;code&gt;RIGHT OUTER JOIN&lt;/code&gt;. Whenever you use &lt;code&gt;RIGHT&lt;/code&gt; or &lt;code&gt;LEFT&lt;/code&gt; in your &lt;code&gt;JOIN&lt;/code&gt;, the &lt;code&gt;OUTER&lt;/code&gt; is implied and you actually don’t have to write it (though some people do because they say it adds clarity).&lt;/p&gt;

&lt;p&gt;There’s one more kind of &lt;code&gt;OUTER&lt;/code&gt; join: &lt;code&gt;FULL&lt;/code&gt;. The &lt;code&gt;FULL OUTER JOIN&lt;/code&gt; will include all results of both the left and rightmost tables, regardless of whether they can be joined to each other. Check it out, the SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
    e.first_name,
    a.street_address
FROM employees e
FULL OUTER JOIN addresses a
ON e.address_id = a.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Bob"   "123 Main St"
"Jordan"    "220 C 30"
"Nicole"    "3030 Burgos"
"Erik"  "1010 2nd St"
"Lina"  "1010 2nd St"
"Sandra"    NULL
NULL    "558 Maple Ave"
NULL    "99 Jackson Rd"
NULL    "821 Carol"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how this time we have all records from each table. The leftmost table, &lt;code&gt;employees&lt;/code&gt;, includes even the record with no associated &lt;code&gt;addresses&lt;/code&gt; record. Likewise, the result set includes three &lt;code&gt;addresses&lt;/code&gt; records with no associated &lt;code&gt;employees&lt;/code&gt; record. That’s because the &lt;code&gt;FULL&lt;/code&gt; join is both a &lt;code&gt;LEFT&lt;/code&gt; and &lt;code&gt;RIGHT&lt;/code&gt; join put together.&lt;/p&gt;

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

&lt;p&gt;Nearly everyone struggles with the different kinds of joins when they’re first learning SQL, so let’s review what we learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LEFT&lt;/code&gt;, &lt;code&gt;RIGHT&lt;/code&gt;, and &lt;code&gt;FULL&lt;/code&gt; joins are the same as &lt;code&gt;LEFT OUTER&lt;/code&gt;, &lt;code&gt;RIGHT OUTER&lt;/code&gt;, and &lt;code&gt;FULL OUTER&lt;/code&gt; joins

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LEFT&lt;/code&gt; will include all records from the leftmost table, even if there are no records in the rightmost table that can join to them&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RIGHT&lt;/code&gt; will include all records from the rightmost table, even if there are no records in the leftmost table that can join to them&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FULL&lt;/code&gt; includes records from both the rightmost and leftmost tables, even if the records from one table have no joining records in the other&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;INNER JOIN&lt;/code&gt; is the default join

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;INNER&lt;/code&gt; will only include records where both the leftmost and rightmost tables have associated records&lt;/li&gt;
&lt;li&gt;Use this when you want only full results; records from one table with no associated records in the other table will not show up in the result set&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Now that you know how to use joins, try out some of them in the example database using the &lt;code&gt;departments&lt;/code&gt; column. As always, feel free to tweet me at @erikwhiting4 or send me an email at &lt;a href="mailto:erik@erikwhiting.com"&gt;erik@erikwhiting.com&lt;/a&gt; if you have any questions. Good luck!&lt;/p&gt;

</description>
      <category>database</category>
      <category>postgres</category>
      <category>sql</category>
    </item>
    <item>
      <title>Is there a Better Label for "Self-Taught" Developers?</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Sun, 08 May 2022 15:22:08 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/is-there-a-better-label-for-8220self-taught8221-developers-5mo</link>
      <guid>https://dev.to/erikwhiting88/is-there-a-better-label-for-8220self-taught8221-developers-5mo</guid>
      <description>&lt;p&gt;If you hang out in software development spaces online long enough, you’ll start to notice there’s a notion of “self-taught” developers. I think it’s time to rethink that label.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Self-Taught Developer?
&lt;/h2&gt;

&lt;p&gt;Before I talk about why I disagree the concept of developers being self-taught, let me first introduce the characteristics most often associated with the label. It’s best to start by talking about what a self-taught developer is &lt;strong&gt;not&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The term self-taught developer is used to describe developers who did not learn their skills from someone else. The following people are typically &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; considered self-taught:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;College students/graduates&lt;/li&gt;
&lt;li&gt;Coding bootcamp graduates&lt;/li&gt;
&lt;li&gt;Someone who was trained on the job&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This implies that the only people who have the supposed right to call themselves self-taught developers are people who picked up their skills by setting out on their own, reading articles, watching videos, digging through documentation, or asking questions online.&lt;/p&gt;

&lt;p&gt;But wait, what’s the difference?&lt;/p&gt;

&lt;h2&gt;
  
  
  Self-Taught vs. Not
&lt;/h2&gt;

&lt;p&gt;On the surface, it seems like the differentiating factor between self-taught developers and developers who aren’t is the presence of someone else doing the teaching. Linguistically, this makes sense, you’re &lt;strong&gt;&lt;em&gt;self&lt;/em&gt;&lt;/strong&gt;-taught because you looked up all the information on your own.&lt;/p&gt;

&lt;p&gt;However, the sources from which a self-taught person gets this information is produced by other people. There are scores of people online writing articles, answering questions, and sharing code, free to be consumed by anyone with an internet connection.&lt;/p&gt;

&lt;p&gt;Why aren’t internet content creators considered teachers? Why does learning Python from a blogger preserve a person’s self-taught label, but learning Python from a professor does not?&lt;/p&gt;

&lt;h2&gt;
  
  
  Proposing a Better Label: Community-Taught Developer
&lt;/h2&gt;

&lt;p&gt;You may be wondering why I care about this. After all, the label isn’t hurting anyone, and it is indeed harder to navigate the programming world on your own; why rob people who figured it out the distinction of calling themselves self-taught?&lt;/p&gt;

&lt;p&gt;I don’t actually want to trivialize the effort required to figure out the programming world with minimal direction. However, a person can learn nearly everything they need to know to be a professional developer from online content produced by many people freely writing articles, making videos, and answering questions on Stack Overflow and other websites.&lt;/p&gt;

&lt;p&gt;The entire community of software developers, over time, have produced a giant corpus of software engineering knowledge. Any time you read language documentation, watch a YouTube video, or read a how-to article about something related to programming, you are consuming the knowledge of the software development &lt;strong&gt;&lt;em&gt;community&lt;/em&gt;&lt;/strong&gt;. I believe the concept of “self-taught” developers discredits that community, or at least makes it seem less important than it is.&lt;/p&gt;

&lt;p&gt;In this way, I believe that most people who call themselves self-taught developers could more accurately describe themselves as “community-taught” developers. This title still indicates that the learner took on most of the initiative to figure out a learning path for themselves, but it also honors the cumulative efforts of the larger community.&lt;/p&gt;

&lt;h2&gt;
  
  
  Am I Bitter?
&lt;/h2&gt;

&lt;p&gt;You may be thinking I’m biased and/or bitter about the idea of people calling themselves self-taught developers because I myself am a university-educated developer. Furthermore, I’m one of those bloggers I was just talking about. Am I just looking for my own kudos? Am I jealous of the self-taught label?&lt;/p&gt;

&lt;p&gt;Perhaps, but consider my learning path and how I arrived at these thoughts about giving credit to the community for my own competence.&lt;/p&gt;

&lt;p&gt;I learned C++ from &lt;a href="https://www.learncpp.com/" rel="noopener noreferrer"&gt;this website&lt;/a&gt; before I ever took a computer-based class in college. I read every word and did all the exercises. Whenever I was stuck, I typed my problem into a search engine and found an answer, usually on Stack Overflow.&lt;/p&gt;

&lt;p&gt;I did all of this on my own, but I don’t feel right calling that “self teaching.” The authors of that website put in countless hours to create a comprehensive and well-written tutorial. Likewise, the people answering questions on Stack Overflow are not usually gaining anything from doing so. Without them, I never would have gotten as far as I did in this field. Calling myself self-taught, I believe, trivializes their efforts.&lt;/p&gt;

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

&lt;p&gt;It’s still a monumental task to take on the responsibility of learning everything you need to know about software development on your own. This article wasn’t intended to minimize those efforts. However, the greater community of developers, writers, and OSS maintainers that put in time to share their knowledge deserve some of the credit, hence why I propose a new title: &lt;strong&gt;&lt;em&gt;community-taught developers&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How to Implement Many-to-Many Relationships in Relational Databases</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Sun, 20 Feb 2022 08:27:30 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/how-to-implement-many-to-many-relationships-in-relational-databases-3311</link>
      <guid>https://dev.to/erikwhiting88/how-to-implement-many-to-many-relationships-in-relational-databases-3311</guid>
      <description>&lt;p&gt;Nearly any data model of non-negligible complexity will include at least one (if not several) many-to-many relationships. This relationship emerges when, given two tables A and B, instances of A could have many instances of B, and instances of B could have many instances of A. Successfully implementing this relationship is a bit of stumbling block for people new to working with or building databases. However, the strategy for implementing this relationship in relational databases is important to understand. Believe it or not, it’s also not all that complicated.&lt;/p&gt;

&lt;p&gt;Once you’ve implemented this relationship a few times, the strategy becomes rather intuitive. However, I remember this concept being one of the hardest ones for me and my classmates to finally understand when it was introduced in second year of undergrad. Hopefully, this article will help you internalize the many-to-many relationship like I eventually did.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is the Many-to-Many Relationship?
&lt;/h1&gt;

&lt;p&gt;The many-to-many (m2m) relationship is a relationship that occurs in data modeling when two entities are related but neither belong to the other and both can have many instances of each other. Here are some examples of many-to-many relationships:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a pet can have many owners, and owners can have many pets&lt;/li&gt;
&lt;li&gt;a language can be spoken by many people, and a person can speak many languages&lt;/li&gt;
&lt;li&gt;a class can have many students, and a student can be in many classes&lt;/li&gt;
&lt;li&gt;a venue can have many visitors, and a visitor can visit many venues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To better understand the many-to-many relationship, let’s briefly talk about the one-to-many relationship to see how the m2m differs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a country can have many cities, but a city can only be in one country&lt;/li&gt;
&lt;li&gt;a car company can make many car models, but each car model is made by only one company&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In each of these examples, note that there is a sense of one entity &lt;em&gt;belonging&lt;/em&gt; to another.&lt;/p&gt;

&lt;h1&gt;
  
  
  Modeling One-to-Many in the Database
&lt;/h1&gt;

&lt;p&gt;One-to-many relationships are easy to model in the database. For example, consider the country-city example. The country India has many cities such as Mumbai, Hyderabad, and Kolkata, but Kolkata only belongs to the country of India.&lt;/p&gt;

&lt;p&gt;So, in the database, we probably have a &lt;code&gt;Country&lt;/code&gt; table that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl57xxtaglgv420ao3ziy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl57xxtaglgv420ao3ziy.png" width="357" height="155"&gt;&lt;/a&gt;Country table with Id and Name columns&lt;/p&gt;

&lt;p&gt;And the &lt;code&gt;City&lt;/code&gt; table plus relationship to the &lt;code&gt;Country&lt;/code&gt; table would look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45m6x79fi2oni8w0a0cw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45m6x79fi2oni8w0a0cw.png" width="277" height="334"&gt;&lt;/a&gt;Country/City relationship&lt;/p&gt;

&lt;p&gt;This is simple enough, and we can query for all cities in a country by simply writing something like &lt;code&gt;SELECT City.Name FROM City JOIN Country ON Country.Id = City.CountryId WHERE Country.Name = 'India'&lt;/code&gt; and we’d get a result set including Mumbai, Hyderabad, Kolkata, and more.&lt;/p&gt;

&lt;p&gt;But this kind of modeling is easy and we’ve only used it as an example to better understand our next section: modeling the many-to-many relationship.&lt;/p&gt;

&lt;h1&gt;
  
  
  Modeling Many-to-Many in the Database
&lt;/h1&gt;

&lt;p&gt;Now let’s consider the more complex many-to-many relationship. Specifically, let’s consider the instance of many people speaking many languages. For example, we might have a Person table and Language table like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5af7w0arebsm2l61wf2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5af7w0arebsm2l61wf2d.png" width="605" height="122"&gt;&lt;/a&gt;Person and Language tables&lt;/p&gt;

&lt;p&gt;Now, suppose we have two people: Erik and Lina. Erik speaks English and Spanish, Lina speaks English and Arabic. This is what we mean by many-to-many relationships; Lina speaks many languages–English and Arabic–and English is spoken by many people–Erik and Lina. So how do we relate the &lt;code&gt;Person&lt;/code&gt; and &lt;code&gt;Language&lt;/code&gt; tables to list out all of the languages a person speaks, or all of the people that speak a language?&lt;/p&gt;

&lt;p&gt;The answer is to create a new table, the &lt;strong&gt;&lt;em&gt;associative table&lt;/em&gt;&lt;/strong&gt;. The associative table sits between the two entities in a many-to-many relationship and actually has a one-to-many relationship with each. That is, given tables A and B and an associative table C, A has many Bs &lt;em&gt;through&lt;/em&gt; C and B has many As &lt;em&gt;through&lt;/em&gt; C; put another way, A has many Cs, B has many Cs, but C has one A and one B.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The associative table are also sometimes called association, bridge, intermediary, join, junction, crosswalk, or linking table (and there’s probably many more names for it). I learned the term “associative” table in undergrad, and I think that’s its official name in relational theory, so that’s what we’ll stick with in this article.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s make this more concrete by creating an associative table for the &lt;code&gt;Person&lt;/code&gt; and &lt;code&gt;Language&lt;/code&gt; relationship. It’s common practice to name association tables as an amalgamation of the tables they join, so we’ll call our associative table &lt;code&gt;PersonLanguage&lt;/code&gt;. I’d create such a table with the following SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE PersonLanguage(
    Id INT IDENTITY(1,1) PRIMARY KEY,
    PersonId INT FOREIGN KEY REFERENCES Person(Id),
    LanguageId INT FOREIGN KEY REFERENCES Language(Id)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we specified two foreign keys on this table, &lt;code&gt;PersonId&lt;/code&gt; and &lt;code&gt;LanguageId&lt;/code&gt;, pointing to the &lt;code&gt;Person&lt;/code&gt; and &lt;code&gt;Language&lt;/code&gt; tables respectively. The table structure now looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmaxstbwr6my0rp8xwtnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmaxstbwr6my0rp8xwtnl.png" width="643" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, there will be a record in the &lt;code&gt;PersonLanguage&lt;/code&gt; table for every language an individual &lt;code&gt;Person&lt;/code&gt; speaks. As a result, there will also be a record in the &lt;code&gt;PersonLanguage&lt;/code&gt; table for every person that speaks a &lt;code&gt;Language&lt;/code&gt;. If we want to see the list of languages Lina speaks, we could run the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT l.name
FROM PersonLanguage pl
JOIN Person p ON p.id = pl.PersonId
JOIN Language l ON l.Id = pl.LanguageId
WHERE p.name = 'Lina'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and we’d get results like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gtuf5b6wysf77ymyjds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gtuf5b6wysf77ymyjds.png" width="267" height="146"&gt;&lt;/a&gt;Results&lt;/p&gt;

&lt;p&gt;Likewise, if we want a list of all the people that speak English, we could run a query like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT p.name
FROM PersonLanguage pl
JOIN Person p ON p.id = pl.PersonId
JOIN Language l ON l.Id = pl.LanguageId
WHERE l.name = 'English'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would give us the following results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrcvr0exdlldnl10ooc9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrcvr0exdlldnl10ooc9.png" width="284" height="146"&gt;&lt;/a&gt;Results&lt;/p&gt;

&lt;h2&gt;
  
  
  Extending the Associative Table
&lt;/h2&gt;

&lt;p&gt;The above examples show the most basic implementation of building associative tables to break up many-to-many relationships. The example &lt;code&gt;PersonLanguage&lt;/code&gt; associative table above only has two columns (besides its own ID column) for pointing to &lt;code&gt;Person&lt;/code&gt; and &lt;code&gt;Language&lt;/code&gt; records.&lt;/p&gt;

&lt;p&gt;We can actually add columns to this table as well and capture interesting information. For example, what if we wanted to record which language was a person’s mother tongue? In other words, if Erik grew up speaking English and learned Spanish later, but Lina grew up speaking Arabic and learned English later, how would we capture that?&lt;/p&gt;

&lt;p&gt;Thanks to the associative table, the answer is pretty easy. We just have to add a column to &lt;code&gt;PersonLanguage&lt;/code&gt; that indicates if the &lt;code&gt;Language&lt;/code&gt; record captured is the &lt;code&gt;Person&lt;/code&gt; record’s primary language. In T-SQL, I’d run the following &lt;code&gt;ALTER&lt;/code&gt; statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE PersonLanguage ADD PrimaryLanguage BIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and set the &lt;code&gt;PrimaryLanguage&lt;/code&gt; value to &lt;code&gt;1&lt;/code&gt; for languages the person learned from birth. By capturing this data on the associative table, we can now write a query to generate a report of every person and their mother tongue like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT p.name AS 'Person', l.Name AS 'Primary Language'
FROM PersonLanguage pl
JOIN Person p ON p.id = pl.PersonId
JOIN Language l ON l.Id = pl.LanguageId
WHERE pl.PrimaryLanguage = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and we’d get results like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Few6mse0bu6g2jrvh3x2v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Few6mse0bu6g2jrvh3x2v.png" width="371" height="154"&gt;&lt;/a&gt;Results&lt;/p&gt;

&lt;p&gt;That is just one example of how to extend the functionality of our database with associative tables.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In this brief article, we learned how to break up many-to-many relationships in relational databases. The general approach is to place an associative table between the two tables and have a one-to-many relationship with them. Then we saw how we can use associative tables to capture nuanced data and create interesting reports. This is an important concept to understand in any kind of software or data engineering work that uses relational databases. As always, I hope this was helpful to you and don’t be afraid to contact me with any questions you might have!&lt;/p&gt;

</description>
      <category>database</category>
      <category>sql</category>
    </item>
    <item>
      <title>Improving Browser Automation Tests: How to Add Microsoft Edge and Edgedriver to Linux CI Systems</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Tue, 28 Sep 2021 23:09:27 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/improving-browser-automation-tests-how-to-add-microsoft-edge-and-edgedriver-to-linux-ci-systems-4jc1</link>
      <guid>https://dev.to/erikwhiting88/improving-browser-automation-tests-how-to-add-microsoft-edge-and-edgedriver-to-linux-ci-systems-4jc1</guid>
      <description>&lt;p&gt;Lately, the Microsoft Edge browser has been growing in popularity, recently unseating Firefox as the 3rd most popular web browser and approaching Safari in the number two spot. This means that any web application with a potentially wide user base should include MS Edge tests in its automated test suite. Setting this up to run automatically, particularly in *nix based CI servers, can be quite a hassle when compared to setting up Chrome and Firefox browser tests. In this article, I’ll show you the steps to get the Edge browser and web driver running in a Linux-like CI system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should I run tests in multiple browsers
&lt;/h2&gt;

&lt;p&gt;If you write web applications, you may only ever test them in the browser of your choice. For example, I use Chrome almost exclusively, and when I write new features for an application, I never really check and see if those features work the same in Firefox, Safari, Edge, or anything else.&lt;/p&gt;

&lt;p&gt;For the most part, you can get away with this, but each browser is a little different and if you’re only testing through one browser, you only know how your web apps look and behave for people using that browser. There are subtle differences between browsers and I’ve received reports of browser-specific bugs from users before that I could’ve caught if I’d just verified my app through something other than Chrome.&lt;/p&gt;

&lt;p&gt;Likewise, you should probably add some variety to your automated test suite and not rely solely on Chrome and Chromedriver for your web-based automated tests. I’m not saying you need to run every feature test in each major browser (though you certainly could) but any test that interacts with or verifies the status or behavior of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The UI&lt;/li&gt;
&lt;li&gt;Cookies&lt;/li&gt;
&lt;li&gt;Session data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;should be tested in at least two popular browsers. These things have the most variability between different browsers, so it’s good practice to verify these attributes with multiple browsers and web drivers.&lt;/p&gt;

&lt;p&gt;Now that we know why we want to test features with multiple browsers, let’s get to the main point of this article: running automated browser tests with Microsoft Edge and Edgedriver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edge-Specific Challenges
&lt;/h2&gt;

&lt;p&gt;The reason an article like this is needed is because most CI pipelines run in Linux-like environments, and Microsoft Edge isn’t really “native” to this operating system. Additionally, many popular CI systems (like CircleCI, TravisCI, GitHub Actions) don’t have out-of-the-box support for Edge and Edgedriver like they do for Chrome and Chromedriver or Firefox and Geckodriver.&lt;/p&gt;

&lt;p&gt;Therefore, we have to add some specific steps in our build files, which we’ll go over in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add MS Edge and Edge Driver to Server
&lt;/h2&gt;

&lt;p&gt;Our general strategy moving forward will be like so:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install Microsoft GPG&lt;/li&gt;
&lt;li&gt;Add MS Edge “dev” distro to sources list&lt;/li&gt;
&lt;li&gt;Install the development version of MS Edge (the browser)&lt;/li&gt;
&lt;li&gt;In the development version of Edgedriver (the Edge-specific web driver)&lt;/li&gt;
&lt;li&gt;Make the driver accessible to the OS&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before I show you the script, there’s one more thing you need: the current Edgedriver development version. We’re going to save ourselves some work by only using the stable dev version of the Edge browser, which we can do by simply specifying “stable” in our script (which you’ll see in a moment) but there is no such easy way to get the latest stable Edgedriver. That’s why we need to go find the specific version.&lt;/p&gt;

&lt;p&gt;To get the version number, go to &lt;a href="https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/" rel="noopener noreferrer"&gt;this page&lt;/a&gt; and look at the version number under “Dev.” As of writing this, the number says 95.0.1020.5. We’ll use this number inside of a URL in our build script. Finally, the script will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor &amp;gt; microsoft.gpg
sudo install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main" &amp;gt; /etc/apt/sources.list.d/microsoft-edge-dev.list'
sudo rm microsoft.gpg
sudo apt update
sudo apt install microsoft-edge-dev
wget https://msedgedriver.azureedge.net/95.0.1020.5/edgedriver_linux64.zip -P ~/
unzip ~/edgedriver_linux64.zip -d ~/
rm ~/edgedriver_linux64.zip
sudo mv -f ~/msedgedriver /usr/local/share/
sudo chmod 777 /usr/local/share/msedgedriver
sudo ln -s /usr/local/share/msedgedriver /usr/local/bin/msedgedriver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script is currently a build step for a personal project of mine and is working fine in GitHub Actions. If you’re using a different CI, the exact syntax of how to lay out the different commands may be different, but the actual commands and their order are correct regardless of CI tool.&lt;/p&gt;

&lt;p&gt;Notice in the &lt;code&gt;wget&lt;/code&gt; command, we have the Edge driver version number in the URL and we’ve specified that we’re using the 64 bit Linux build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues with Local vs Remote Driver
&lt;/h2&gt;

&lt;p&gt;There is one issue I was running into when trying to run my tests in a remote CI server. I don’t remember the specifics of the issue, nor do I know if it will be the same in all Selenium ports (I use Python) but basically the issue is this: When you’re using the dev version of the browser and driver for edge, you have to tell Selenium you’re doing so or the tests will not find the driver.&lt;/p&gt;

&lt;p&gt;My approach to fixing this issue is to set an environment variable in the CI script such as &lt;code&gt;RUNNING_IN_CI=True&lt;/code&gt; or something similar and then check for that variable in the test. If it’s not there, that means I’m running tests locally and I don’t need to specify that I’m using the dev version. If that variable is present however, I need to set the following values (this is specific to LuluTest browser automation framework, but your implementation of Selenium will likely be similar):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;options_hash = BrowserOptions({
    'driver_type': browser,
    'headless': True,
    'browser_binary_location': shutil.which('microsoft-edge-dev'),
    'webdriver_location': shutil.which('msedgedriver'),
    'operating_system': 'LINUX'
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I’m using Python’s &lt;code&gt;shutil&lt;/code&gt; library to find the path of Microsoft Edge and Edgedriver in the CI system, as well as some other housekeeping things. This is necessary if you’ve used a build script like mine above.&lt;/p&gt;

&lt;p&gt;That should do it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Join my OSS Browser Automation Project!
&lt;/h2&gt;

&lt;p&gt;Thanks for reading this article, I hope it helped you. If you like browser automation and open-source software, consider checking out my OSS project &lt;a href="https://github.com/erik-whiting/LuluTest" rel="noopener noreferrer"&gt;LuluTest&lt;/a&gt; and adding some contributions. I’m looking for developers, testers, and writers alike! I’ve tried to make the project as beginner friendly and inclusive as possible so with #hacktoberfest 2021 coming up, maybe you can knock out some of your PRs with me.&lt;/p&gt;

</description>
      <category>ci</category>
      <category>hacktoberfest</category>
      <category>testing</category>
    </item>
    <item>
      <title>Professional Version Control with Git: Pt 3 – Rebase and Bisect</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Sat, 10 Jul 2021 19:39:18 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/professional-version-control-with-git-pt-3-rebase-and-bisect-163k</link>
      <guid>https://dev.to/erikwhiting88/professional-version-control-with-git-pt-3-rebase-and-bisect-163k</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/erikwhiting88/professional-version-control-with-git-pt-1-the-basics-3ahm"&gt;Part 1 - The Basics&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/erikwhiting88/professional-version-control-with-git-pt-2-collaboration-26mp"&gt;Part 2 - Collaboration&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello everyone and welcome to part 3 of the professional Git series here at Erik’s Code Space. In &lt;a href="https://erikscode.space/index.php/2021/03/26/professional-version-control-with-git-pt-1-the-basics/" rel="noopener noreferrer"&gt;part 1&lt;/a&gt;, we learned the basics and got our skills good enough to start version controlling our own projects. In &lt;a href="https://erikscode.space/index.php/2021/04/05/professional-version-control-with-git-pt-2-collaboration/" rel="noopener noreferrer"&gt;part 2&lt;/a&gt;, we learned about the collaboration tools available in git and got our skills good enough to start contributing to open source projects. In this part, we’re going to learn about the rebase and bisect commands, two commands that help us with troubleshooting. Without further ado, let’s begin.&lt;/p&gt;
&lt;h2&gt;
  
  
  Keeping History Clean
&lt;/h2&gt;

&lt;p&gt;In part 1, we learned about how our commit messages become the official “history” of our projects. The git history is supposed to keep a timeline-like record of the growth and change of our repository, so we try to keep our commit messages accurate and helpful, so then when someone runs a &lt;code&gt;git log&lt;/code&gt; command against our repo, they get an accurate idea of how the project has been evolving lately.&lt;/p&gt;

&lt;p&gt;Sometimes though, we need to rewrite history, or get rid of it completely. Maybe we made a bad commit, made a typo in our commit message, or need to combine two commits into one. That’s where &lt;code&gt;git rebase&lt;/code&gt; comes in! Let’s get started; make a directory called &lt;code&gt;rebase_and_bisect&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt; into it, and run the &lt;code&gt;git init&lt;/code&gt; command. If you’re using a Linux or Mac terminal, or GitBash for Windows, the following commands will do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; mkdir rebase_and_bisect
$&amp;gt; cd rebase_and_bisect
$&amp;gt; git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now make a file called &lt;code&gt;poem.txt&lt;/code&gt; and commit it to the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; touch poem.txt
$&amp;gt; git add .
$&amp;gt; git commit -m "Create file"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we’ll populate that file with a beautiful poem I’ve written. We will add one line at a time and commit that changes before writing the next line. I will share the commands to do this below, without the command prompt (the &lt;code&gt;$&amp;gt;&lt;/code&gt;) so that you can copy and paste them into your terminal, saving you some time. (Please note, the following commands will probably not work with PowerShell or CMD, please use GitBash if you’re on Windows):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Roses are red" &amp;gt; poem.txt
git commit -am "Add first line"
echo "JavaScript is yellow" &amp;gt;&amp;gt; poem.txt
git commit -am "Add second line"
echo "I'm learning git" &amp;gt;&amp;gt; poem.txt
git commit -am "Add third line"
echo "and I wanna say hello!" &amp;gt;&amp;gt; poem.txt
git commit -am "Add fourth line"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might have to manually press “enter” one more time, but you should now have a four line poem in &lt;code&gt;poem.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There’s one more piece of housekeeping we have to do before we get on with the rest of this tutorial, setting up our git editor. The git editor is the text processing program that opens when you do things with git that require editing text. I believe the default text editor on GitBash is vim, which isn’t user friendly. Personally, I like nano, so in order to set my default git text editor to nano, I would run the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git config --global core.editor "nano -w"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to use a different program, you have to pass the path to that program in place of where I put &lt;code&gt;nano -w&lt;/code&gt;. For a more exhaustive list of how to set specific text editors, click &lt;a href="https://www.git-scm.com/book/tr/v2/Appendix-C%3A-Git-Commands-Setup-and-Config?fbclid=IwAR0pC9Cf4DO8dWPzYQCaxb9qKONlCJW0nPg8XH7IO5cuj2-hcqKuprzwgmY" rel="noopener noreferrer"&gt;this&lt;/a&gt; link.&lt;/p&gt;

&lt;p&gt;With this out of the way, let’s learn about &lt;code&gt;rebase&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rebase
&lt;/h2&gt;

&lt;p&gt;We learned in part 1 that commit messages make up the history of our project. When someone runs &lt;code&gt;git log&lt;/code&gt;, they see all the commit messages made on the project. Our goal is to write concise yet descriptive messages of the work we’ve done so that the collection of commit messages show an accurate picture of where our project came from and how it’s evolving.&lt;/p&gt;

&lt;p&gt;Sometimes though, we make mistakes with our commit messages. We could make a typo, duplicate commits, or commit something we really didn’t mean to. Once we’ve made the commit though, the damage is already done, right? Wrong! With &lt;code&gt;git rebase&lt;/code&gt;, we can rewrite history!&lt;/p&gt;

&lt;h3&gt;
  
  
  Making Bad Commit Messages
&lt;/h3&gt;

&lt;p&gt;One of the main uses of using &lt;code&gt;git rebase&lt;/code&gt; is rewriting commit messages. We’ll open up &lt;code&gt;poem.txt&lt;/code&gt; in our text editor of choice and sign our name at the bottom. Then we’ll commit the changes but, oh no! We make a typo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git commit -am "Signing my nammee"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;git log&lt;/code&gt; to see the typo in our list of otherwise good commit messages. We’re now going to use &lt;code&gt;rebase&lt;/code&gt; to fix this. We’re going to use the &lt;em&gt;interactive&lt;/em&gt; version of rebase to do this, and we’re going to &lt;em&gt;go back one commit&lt;/em&gt; when rebasing. So the command I want you to run is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git rebase &amp;lt;strong&amp;gt;-i&amp;lt;/strong&amp;gt; HEAD&amp;lt;strong&amp;gt;~1&amp;lt;/strong&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-i&lt;/code&gt; is for “interactive” and the &lt;code&gt;HEAD~1&lt;/code&gt; means “go back one commit from the latest version.” As soon as you hit enter, you should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw8f1k7r5vz25iwyjosfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw8f1k7r5vz25iwyjosfw.png" width="601" height="397"&gt;&lt;/a&gt;Let’s talk about what we’re looking at real quick. This text file is called &lt;code&gt;git-rebase-todo&lt;/code&gt; and lives inside the local &lt;code&gt;.git&lt;/code&gt; directory for this project. The first line is the commit we’ve rolled back to, the one with the typo. Below that is a few lines to help users figure out what to do from here, and is pretty helpful once you get the hang of rebasing. For now though, I’ll just walk you through the next few steps.&lt;/p&gt;

&lt;p&gt;So the goal here is to fix the typo from our last commit message. That means that we want to “reword” the commit message, so on the first line, delete &lt;code&gt;pick&lt;/code&gt; and type &lt;code&gt;reword&lt;/code&gt;. Then, save the file and exit it (if you’re using nano, you save by pressing “Ctrl + o” then press enter and exit with “Ctrl + x”).&lt;/p&gt;

&lt;p&gt;Once you’ve closed the file, another one will open containing the commit message for that particular commit. Mine looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6phj73q72sm77qxdd1ti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6phj73q72sm77qxdd1ti.png" width="674" height="300"&gt;&lt;/a&gt;Scroll over to &lt;code&gt;nammee&lt;/code&gt; and change it to &lt;code&gt;name&lt;/code&gt;, save, and exit. You’ll be returned to the terminal with a message about successfully rebasing. Run &lt;code&gt;git log&lt;/code&gt; again and what do you notice? The typo from our last commit message is gone and our history is saved! Here’s what mine looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcf1z9dt4mfejz8b0d7mf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcf1z9dt4mfejz8b0d7mf.png" width="626" height="538"&gt;&lt;/a&gt;#### Did you get Stuck in Vim?&lt;/p&gt;

&lt;p&gt;If you missed the part about setting your default text editor and your files opened in a text editor that doesn’t seem to make sense, you might be in vim. Don’t panic, I’ll walk you through getting out of this. First, check and see that you really are in vim. If you are, you’ll notice that all the lines below the commented-out portion (the portion preceded by &lt;code&gt;#&lt;/code&gt;s) are all tildes (&lt;code&gt;~&lt;/code&gt;). In my GitBash, vim looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r13ze070qlvkqe30kfq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r13ze070qlvkqe30kfq.png" width="582" height="506"&gt;&lt;/a&gt;Operating vim is a little weird if you’re not used to it. When it first opens, you’re in “normal” mode and you can’t edit text the way you think you can. To enter “insert” mode, just type the letter &lt;code&gt;i&lt;/code&gt;. Once you’ve done this, you can edit the text like you would in a normal program, using the arrows to maneuver around and the backspace and delete buttons the way you’d expect.&lt;/p&gt;

&lt;p&gt;Once you’ve changed “pick” to “reword,” you have to go back into “normal” mode by pressing the &lt;code&gt;Esc&lt;/code&gt; key. Once you’ve done this, you can save the file by first pressing the key combination for colon (&lt;code&gt;:&lt;/code&gt;) which is Shift + ;. You’ll notice now that your cursor is now at the bottom left of the screen. Type &lt;code&gt;wq!&lt;/code&gt; and then press enter. This is the command for saving and exiting (or &lt;strong&gt;w&lt;/strong&gt;riting and &lt;strong&gt;q&lt;/strong&gt;uitting). Repeat the process when it opens the commit message file and you should be good to go!&lt;/p&gt;

&lt;h3&gt;
  
  
  Consolidate Commits
&lt;/h3&gt;

&lt;p&gt;Sometimes, I forget to do a whole task before I commit it. As an example, say I wanted to remove my name from &lt;code&gt;poem.txt&lt;/code&gt; file. I open it up, delete my name, save, the file, then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git commit -am "Removed name"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But then I realize that I didn’t also delete the empty line my name was on. So I go in and delete that line, which was really part of the name-deleting work so I make a silly commit message like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git commit -am "Finish removing name"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now my history looks a little weird because I have two commits for deleting my name. There’s nothing really wrong with this except that I want my git history to be clean. In order to do that, I decide I want to put the last two commits together. So I need to do another interactive &lt;code&gt;rebase&lt;/code&gt;, this time going back &lt;strong&gt;&lt;em&gt;two&lt;/em&gt;&lt;/strong&gt; commits, so I run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git rebase -i HEAD~2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, when the &lt;code&gt;git-rebase-todo&lt;/code&gt; file opens, I have the last two commits listed. This means I want to &lt;strong&gt;&lt;em&gt;squash&lt;/em&gt;&lt;/strong&gt; the most recent commit into the last one, so I change &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;squash&lt;/code&gt; on the second line:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flja5ydq9w8pzacpnl2yb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flja5ydq9w8pzacpnl2yb.png" width="638" height="155"&gt;&lt;/a&gt;On the next screen, I will pick the commit message I want to keep. I’m going to remove the &lt;code&gt;Finish removing name&lt;/code&gt; message by commenting it out, the file will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76ux6zbi0yrnhyi5xf0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76ux6zbi0yrnhyi5xf0i.png" width="587" height="380"&gt;&lt;/a&gt;Notice that I added the &lt;code&gt;#&lt;/code&gt; symbol in front of the line underlined in red. From here, save and exit this file again to return to the terminal. Run &lt;code&gt;git log&lt;/code&gt; once again and what do you notice? We’ve successfully merged the last two commits into a single commit, keeping our history clean!&lt;/p&gt;

&lt;p&gt;There’s a ton more you can do with &lt;code&gt;rebase&lt;/code&gt; and I encourage you to read the commented lines detailing the commands in the &lt;code&gt;git-rebase-todo&lt;/code&gt; file. Play around with it some to get a feel for what you can do with this useful tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bisect
&lt;/h2&gt;

&lt;p&gt;Git’s &lt;code&gt;bisect&lt;/code&gt; command is pretty cool because it helps us locate the source of a bug by searching for the specific commit a bug was introduced. The way it works is we first identify a “bad” commit, or a commit in which a bug exists, then we identify a commit in which the bug does not exist, or a “good” commit. Then, git will checkout old commits between the good and bad ones and ask us if the bug still exists.&lt;/p&gt;

&lt;p&gt;Then, by process of elimination, we eventually pinpoint the exact commit that broke introduced the problem. It might sound confusing, so let’s just get hands on with it. I’m going to give you another list of terminal commands to run. One of which will intentionally introduce a bug, which we’ll then pinpoint with the &lt;code&gt;bisect&lt;/code&gt; tool. Run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "This poem is about JavaScript" &amp;gt;&amp;gt; poem.txt
git commit -am "Add description of poem"
sed -i -e 's/yellow/orange/g' poem.txt
git commit -am "Replace 'yellow' with 'orange'"
echo "This is for my git tutorial" &amp;gt;&amp;gt; poem.txt
git commit -am "Add reason for poem"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, take a look at the contents of &lt;code&gt;poem.txt&lt;/code&gt; and note the bug, “yellow” seems to have been replaced with “orange.” See for yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; cat poem.txt
Roses are red
JavaScript is &amp;lt;strong&amp;gt;orange&amp;lt;/strong&amp;gt;
I'm learning git
and I wanna say hello!
This poem is about JavaScript
This is for my git tutorial

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

&lt;/div&gt;



&lt;p&gt;We’re now going to use &lt;code&gt;bisect&lt;/code&gt; to identify the commit that introduced this bug. The first thing we have to do is identify a good commit–where the bug doesn’t exist–and a bad commit–where the bug does exist. Run &lt;code&gt;git log&lt;/code&gt; to find these commits. Please note that your commit hashes will not match mine, so for the rest of the article, you cannot copy/paste my example commands, you’ll have to use your relevant commit hashes.&lt;/p&gt;

&lt;p&gt;My git log looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjg95mkbiqei9nox3wn0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjg95mkbiqei9nox3wn0v.png" width="487" height="654"&gt;&lt;/a&gt;Since I know that the bug currently exists, I’m going to call my most recent commit (&lt;code&gt;b33c81d&lt;/code&gt;) the bad one, and I know that the second line still said “yellow” when I signed my name, so I’m going to call that commit (&lt;code&gt;00b7e71&lt;/code&gt;) the good one.&lt;/p&gt;

&lt;p&gt;Now, I need to &lt;code&gt;start&lt;/code&gt; the bisect wizard by running &lt;code&gt;git bisect start&lt;/code&gt;, then identify the good and bad commits with &lt;code&gt;git bisect good [hash]&lt;/code&gt; and &lt;code&gt;git bisect bad [hash]&lt;/code&gt;. Take a look:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gq8vi2sqq9rgqi1lxol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gq8vi2sqq9rgqi1lxol.png" width="800" height="191"&gt;&lt;/a&gt;Git then picks a commit between the good and bad ones. From here, we’re supposed to check and see if the bug still exists, if it does, we tell it with &lt;code&gt;bad&lt;/code&gt; if not, we use &lt;code&gt;good&lt;/code&gt;. So check the file for the bug:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; cat poem.txt
Roses are red
JavaScript is yellow
I'm learning git
and I wanna say hello!
This poem is about JavaScript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The word “yellow” is still there, so we run &lt;code&gt;git bisect good&lt;/code&gt;. Git then picks another commit between this one and the commit we marked as bad. Take a look:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20w732hx96ibybiczxzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20w732hx96ibybiczxzc.png" width="760" height="183"&gt;&lt;/a&gt;When we check the contents of the &lt;code&gt;poem.txt&lt;/code&gt; file, we see that we called JavaScript “orange” instead of “yellow.” So we mark this one as bad with &lt;code&gt;git bisect bad&lt;/code&gt;. With this information, git now believes it’s found the commit that introduced the bug. It correctly identifies the commit in which we replaced “yellow” with “orange” (for me, commit &lt;code&gt;d5ebcc3&lt;/code&gt;) as the offending commit.&lt;/p&gt;

&lt;p&gt;We’ll now exit the bisect wizard by running &lt;code&gt;git bisect reset&lt;/code&gt; which returns us back to the most recent commit. Now that we know which commit introduced the “yellow -&amp;gt; orange” bug, we’ll use &lt;code&gt;rebase&lt;/code&gt; to get rid of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Rebase to Fix Bug
&lt;/h3&gt;

&lt;p&gt;Since we know the commit that introduced the bug, we should check and see what was going on with that commit. We can compare the commit with it’s previous commit to see what changes were made by using the &lt;code&gt;git diff&lt;/code&gt; command and passing in two hashes.&lt;/p&gt;

&lt;p&gt;For me, the hash for the bad commit was &lt;code&gt;d5ebcc3&lt;/code&gt;. If I want to reference the commit before that without looking up its hash, I can append &lt;code&gt;~1&lt;/code&gt; to the hash as something of a relative way of referencing the previous commit. In other words, if I want to compare &lt;code&gt;d5ebcc3&lt;/code&gt; and the commit prior to it with &lt;code&gt;diff&lt;/code&gt;, I would run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git diff d5ebcc3&amp;lt;strong&amp;gt;~1&amp;lt;/strong&amp;gt; d5ebcc3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output then shows me what changed in that commit, see my screenshot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngyge7exlqee3qf6ts6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngyge7exlqee3qf6ts6g.png" width="613" height="239"&gt;&lt;/a&gt;Since I can see from this diff that nothing other than changing the word “yellow” to “orange” happened in this commit, I can safely assume that the whole commit can be removed from the project’s git history. I will use rebase to expunge any record of that commit ever taking place. To do this, I need to do another interactive rebase, this time to the commit before &lt;code&gt;d5ebcc3&lt;/code&gt;. In order to this, I run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git rebase -i d5ebcc3~1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This brings us back to &lt;code&gt;git-rebase-todo&lt;/code&gt; file we saw earlier. This time, I’m going to &lt;code&gt;drop&lt;/code&gt; the offending commit. Not only will that remove that commit’s message from the project’s history, it’ll also get rid of the changes made in that commit. Make your file look like mine (but don’t change the commit hashes):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdmxkiujnnqcfrcsd2f7m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdmxkiujnnqcfrcsd2f7m.png" width="602" height="225"&gt;&lt;/a&gt;Save and exit the file and you’ll be returned to the terminal with the message “Successfully rebased and updated refs/heads/main.” First, let’s make sure the bug is fixed. &lt;code&gt;cat&lt;/code&gt; the contents of &lt;code&gt;poem.txt&lt;/code&gt; and make sure JavaScript is yellow again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; cat poem.txt
Roses are red
JavaScript is yellow
I'm learning git
and I wanna say hello!
This poem is about JavaScript
This is for my git tutorial

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

&lt;/div&gt;



&lt;p&gt;Great! The bug has been fixed, now run &lt;code&gt;git log&lt;/code&gt; and note that the offending commit has been stricken from the record:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0grylu9bl1oh35r36olk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0grylu9bl1oh35r36olk.png" width="800" height="724"&gt;&lt;/a&gt;And now we know how to use &lt;code&gt;bisect&lt;/code&gt; to locate bugs and &lt;code&gt;rebase&lt;/code&gt; to get rid of them!&lt;/p&gt;

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

&lt;p&gt;That concludes part 3 of the Professional Version Control with Git series. In part 1, we learned the basics of using git for our own projects, then in part 2 we learned about the tools for collaboration. Finally, in this part, we learned how to use &lt;code&gt;rebase&lt;/code&gt; to keep our history clean, and &lt;code&gt;bisect&lt;/code&gt; to help us track down bugs. That concludes the Professional Version Control with Git series, but keep an eye out for more content about version control and collaboration tools. Don’t hesitate to contact me with any questions you have by emailing &lt;a href="mailto:ewhiting@erikscode.space"&gt;ewhiting@erikscode.space&lt;/a&gt; or hitting me up on Twitter, &lt;a href="https://twitter.com/ErikWhiting4" rel="noopener noreferrer"&gt;@ErikWhiting4&lt;/a&gt;. Thanks, and see you next time!&lt;/p&gt;

</description>
      <category>bisect</category>
      <category>git</category>
      <category>rebase</category>
    </item>
    <item>
      <title>Professional Version Control with Git: Pt 2 - Collaboration</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Sat, 10 Jul 2021 19:38:08 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/professional-version-control-with-git-pt-2-collaboration-26mp</link>
      <guid>https://dev.to/erikwhiting88/professional-version-control-with-git-pt-2-collaboration-26mp</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/erikwhiting88/professional-version-control-with-git-pt-1-the-basics-3ahm"&gt;Part 1 - The Basics&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/erikwhiting88/professional-version-control-with-git-pt-3-rebase-and-bisect-163k"&gt;Part 3 - Rebase and Bisect&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Welcome back, this article is part 2 of Erik’s Code Space’s series on professional version control with Git. In &lt;a href="https://erikscode.space/index.php/2021/03/26/professional-version-control-with-git-pt-1-the-basics/" rel="noopener noreferrer"&gt;part one&lt;/a&gt;, we learned about the basics of making commits, branching, and merging. In this section, we’re going to learn about the collaboration tools available to us with Git through GitHub. Let’s get started!&lt;/p&gt;

&lt;p&gt;In this part of the Git series, we’re going to learn about the tools that exist to help us collaborate with other developers. We’re going to learn about three general concepts: publishing, cloning , and making pull requests.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Publishing&lt;/em&gt;&lt;/strong&gt; is when we put our own projects out into the world to be viewed, downloaded, and tweaked by anyone. This is what people mean when they tell you to have your own side projects up for potential employers to see.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Cloning&lt;/em&gt;&lt;/strong&gt; is when you copy someone else’s project onto your own computer so that you can work on or use it. In Git, “cloning” is almost synonymous with “downloading.” Instead of downloading binaries of a program though, we get the actual source code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Pull Requests&lt;/em&gt;&lt;/strong&gt; (sometimes called &lt;strong&gt;&lt;em&gt;Merge Requests&lt;/em&gt;&lt;/strong&gt;) are what you create when you’ve made changes to a project and you want to merge it into the main project. Recall that in part one we learned that &lt;em&gt;merging&lt;/em&gt; meant adding events to the true history of a project. When you collaborate with other developers, your changes typically need to be reviewed before they’re merged into a project.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Setting Up Your GitHub Profile
&lt;/h2&gt;

&lt;p&gt;If you haven’t already, you should &lt;a href="https://github.com/join?ref_cta=Sign+up&amp;amp;ref_loc=header+logged+out&amp;amp;ref_page=%2F&amp;amp;source=header-home" rel="noopener noreferrer"&gt;head over to GitHub and sign up&lt;/a&gt;; don’t worry, it’s free. Signing up should be pretty straightforward basic stuff. You don’t have to worry about stuff like your About Me, profile picture, and other stuff if you don’t want to. Just finish setting up and get to your homepage.&lt;/p&gt;

&lt;p&gt;Once you’ve set up your profile, we need to get your local Git configuration aligned with your profile information. Open up your command line of choice so we can start on this. The commands you should run are the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git config --global user.name "username"
$&amp;gt; git config --global user.email "your_eamil@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing we need to do is get SSH enabled. Personally, I hate this step and any time I have to redo this step, I have to go and relearn to do it. The official docs for doing this are really great if you want a much more precise guide to it than I’m about to give you, they can be found &lt;a href="https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generating an SSH Key
&lt;/h3&gt;

&lt;p&gt;If you’ve decided to stick with me, the first thing we have to do is generate an SSH key. If you’re on Linux, you should already have the ability to do this from the terminal with &lt;code&gt;ssh-keygen&lt;/code&gt;. If you’re on Windows, the best way to do this is with Git Bash, which should have come with your installation of Git. If not, go back to &lt;a href="https://git-scm.com/downloads" rel="noopener noreferrer"&gt;the download page&lt;/a&gt; and download it again. You can find Git Bash by typing bash into your search box and clicking this icon:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn0zw4q3v5du6sd6o9jp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn0zw4q3v5du6sd6o9jp.png" width="380" height="128"&gt;&lt;/a&gt;From the Bash terminal, run &lt;code&gt;ssh-keygen -t rsa -b 4096 -C "your_email@example.com"&lt;/code&gt;. The resulting prompt will ask you what path and filename to save the key into, put something like “~/.ssh/gittutorial” or something you’ll be able to remember. The next question will ask you to make a passphrase; this is optional and is just for providing a bit of extra security. You can just press enter to go with no passphrase.&lt;/p&gt;

&lt;p&gt;Now we need to add our key to the ssh-agent. To be honest with you, I don’t really understand the point of this step, but I know it’s necessary, so let’s power through it together. First, you need to make sure the ssh-agent is running. It probably is but just in case, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; eval `ssh-agent -s`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the characters around &lt;code&gt;ssh-agent&lt;/code&gt; are backticks (Shift + ~). If after running this command you see something like “Agent pid 5278”, you’re good to go. If not, please refer to &lt;a href="https://docs.github.com/en/github/authenticating-to-github/working-with-ssh-key-passphrases" rel="noopener noreferrer"&gt;this article&lt;/a&gt; on the GitHub docs.&lt;/p&gt;

&lt;p&gt;Once we know the agent is running, we simply add our newly generated key with &lt;code&gt;ssh-add ~/.ssh/gittutorial&lt;/code&gt;. You will be prompted again for your passphrase, just retype it or press enter if you didn’t make one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding SSH Key to GitHub Account
&lt;/h3&gt;

&lt;p&gt;Now we need to add your public SSH key to the GitHub profile. On GitHub, click your profile thumbnail in the top right of the screen and click “settings.” From here, go to “SSH and GPG keys” in the left menu. Click “New SSH key” at the top. In the next screen, give your SSH key a title. I typically name the keys after whatever computer that key is for.&lt;/p&gt;

&lt;p&gt;Now, head back to your terminal and run &lt;code&gt;cat ~/.ssh/gittutorial.pub&lt;/code&gt; and copy the output (if you have a program called clip installed, you can run &lt;code&gt;clip &amp;lt; ~/.ssh/gittutorial.pub&lt;/code&gt;). Back in your browser, paste the contents into the “key” field. Check carefully for an errant line break, if your key ends with your email, but your cursor is on the next line, hit backspace to get rid of that character.&lt;/p&gt;

&lt;p&gt;Click “Add SSH Key” when you’re done and that should be the end of that. Everything we just did is so that we can clone and push repositories remotely. Getting this out of the way will save us some time for the rest of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make a New Repository
&lt;/h2&gt;

&lt;p&gt;Now that our profile is ready to go, it’s time to make a new repository. As a reminder, a “repository” is another name for a project’s source code. In part one, we likened it to a company with our commits being the company’s timeline. The “repository” is where all our code will live. From now on, I will call the repository the “repo.”&lt;/p&gt;

&lt;p&gt;From the GitHub homepage, in the left menu, you should see a button that says “New” with a book icon. Click it! The next screen will ask you to name the repo, I’m going to go with “ecs-git-tutorial.”&lt;/p&gt;

&lt;p&gt;The next selection is the choice to make the repo public or private. I typically keep my repositories private until they’re ready to be used or viewed, but I will keep this one public and I invite you to do the same. Finally, click the option about generating a README and then click “Create repository.”&lt;/p&gt;

&lt;p&gt;The next screen will be pretty boring, it’s the home page and README of your mostly empty repository. You’ve officially created a repository on GitHub. It may be a small step but congratulations anyway!&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloning The Repository
&lt;/h2&gt;

&lt;p&gt;As I mentioned earlier, cloning a repository means to copy it’s contents into your local computer. This is a fairly straightforward process, so let’s jump right into it.&lt;/p&gt;

&lt;p&gt;On your repo’s main page, there should be a green button that says “Code” with a down arrow. Click it and select the SSH option. Copy the address in the input bar by clicking the clipboard icon on the right of the Clone pop up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx49zxdapcgiwtiq6jygx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx49zxdapcgiwtiq6jygx.png" width="800" height="279"&gt;&lt;/a&gt;Go back to your command prompt and type &lt;code&gt;git clone git@github.com:user/project&lt;/code&gt; replacing the part after “clone” with the thing you just copied. For example, for me to clone the repository I just created, I would run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git clone git@github.com:erik-whiting/ecs-git-tutorial.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yours will be slightly different. After you hit enter, you’ll see a few outputs and finally you’ll get your prompt back. Run &lt;code&gt;dir&lt;/code&gt; or &lt;code&gt;ls&lt;/code&gt; to see the contents and notice that there’s now a folder called &lt;code&gt;ecs-git-tutorial&lt;/code&gt;. Go ahead and &lt;code&gt;cd&lt;/code&gt; into it and run &lt;code&gt;ls&lt;/code&gt; again. Notice that the README is in there. That’s the same README you see on your repository’s homepage on GitHub. We’ve successfully cloned the repo onto our local machine!&lt;/p&gt;

&lt;p&gt;Now that you know how to do this, you know how to clone just about any project that’s maintained on GitHub. For example, one of the most popular repos for GitHub is &lt;a href="https://github.com/willmcgugan/rich" rel="noopener noreferrer"&gt;rich&lt;/a&gt;, a project that gives you “rich text and beautiful formatting in the terminal.” If you wanted to look through the code of that project on your own IDE, you know how to do that now: with &lt;code&gt;git clone&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making Changes and Pushing
&lt;/h2&gt;

&lt;p&gt;Most of the time you clone a project from GitHub, it’s so that you can make your own contributions and push them. Let’s do that right now to get a feel for it. Make a new file called “tutorial.txt” and put something simple in there like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hi, I'm a text file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the file to the repository with &lt;code&gt;git add tutorial.txt&lt;/code&gt; and make a simple commit, something like &lt;code&gt;git commit -m "First commit"&lt;/code&gt;. Now we’ve got this tutorial.txt file and commit history on our local computer only. We now want to publish our changes by &lt;strong&gt;&lt;em&gt;pushing&lt;/em&gt;&lt;/strong&gt; them. To push your changes to the repo, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once again, you’ll see a few outputs in the terminal. If everything went according to plan, we just successfully pushed the tutorial.txt file to GitHub. Go back to your browser and refresh your repo’s homepage. You should now see a new file called “tutorial.txt” with “First commit” and how long ago you committed the file. mine looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsnrj1eo51afev3wn4j6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsnrj1eo51afev3wn4j6.png" width="800" height="328"&gt;&lt;/a&gt;Pretty cool right? We’ve gotten the changes we made on our local machine up to GitHub where anyone can see them. This means anyone with access to GitHub can now clone our work and collaborate with us!&lt;/p&gt;

&lt;p&gt;Typically, pushing changes directly to the main branch is considered very bad practice. We generally use a workflow involving “pull requests,” which we’ll learn about next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Pull Request
&lt;/h2&gt;

&lt;p&gt;Most of the time when we collaborate on projects with multiple developers, or even when we’re working on our own projects, we don’t want to do work on the main branch. Instead, we follow a workflow that involves creating a new branch locally, doing our work, publishing the branch in the repository, and creating a &lt;strong&gt;&lt;em&gt;pull request&lt;/em&gt;&lt;/strong&gt; for it. Let’s go through this workflow together.&lt;/p&gt;

&lt;p&gt;From your terminal, create a new branch called “edit-tutorial.txt.” If you forgot how to do that, the following command will create and checkout the branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git checkout -b edit-tutorial.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, open up the tutorial.txt file and add another line to it, something like “This line was added from the edit-tutorial.txt branch.” From your terminal, run &lt;code&gt;git status&lt;/code&gt; to make sure you see that tutorial.txt has been modified. Go ahead and commit these changes with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git commit -am "Add line to tutorial.txt"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After committing, run &lt;code&gt;git push&lt;/code&gt;. Notice that we get an error that says&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;fatal: The current branch edit-tutorial.txt has no upstream branch. To push the current branch and set the remote as upstream, use&lt;/p&gt;

&lt;p&gt;git push –set-upstream origin edit-tutorial.txt&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What happened here? Well, we tried to publish our changes to a branch that doesn’t exist &lt;strong&gt;&lt;em&gt;upstream&lt;/em&gt;&lt;/strong&gt;, or in our repo on GitHub. Right now, the only branch on GitHub should be &lt;code&gt;main&lt;/code&gt;. We have to create the branch on GitHub in order to publish our local branch. Doing so is as easy as running the command suggested by the error message though, so simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git push --set-upstream origin edit-tutorial.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The terminal will again output some information. Once it’s done, go back to the repo’s homepage. You should see a message about a branch having new pushes with a button to “Compare &amp;amp; pull request” like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhp86qre30erkrfmu0tx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhp86qre30erkrfmu0tx.png" width="800" height="204"&gt;&lt;/a&gt;Just in case you don’t see that though, you can click “Pull Requests” in the menu, and click “New pull request” in the next screen. In the next screen, you’d have to change the “compare” dropdown to “edit-tutorial.txt” and click “Create pull request” to create the pull request or PR.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrvu5th52u2qvoas0mdr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrvu5th52u2qvoas0mdr.png" width="800" height="220"&gt;&lt;/a&gt;In the next screen, you’re given the option to title and write a comment about the PR. The default title is the last commit message, but I typically like to name them something more official sounding. I also like to add a little description to the PR, but it’s not required. Here’s what my PR looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqx0gn7muk2n61c3qt27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqx0gn7muk2n61c3qt27.png" width="800" height="501"&gt;&lt;/a&gt;Now, before finishing the creation of the PR, scroll down on this page and notice that you can now see the incoming changes. I prefer “Split” view to “Unified” (those options are in the top right of the screen relative to the file comparison section of the screen). On the left you’ll see the code that exists in the &lt;code&gt;main&lt;/code&gt; branch, on the right you’ll see the changes made highlighted in green (deletions would be highlighted in red). This is usually a good time to look over the changes you’ve made to make sure you didn’t miss anything important.&lt;/p&gt;

&lt;p&gt;Go ahead and click the “Create pull request” button to finish creating the PR. You’ll then be taken to the homepage of the PR&lt;/p&gt;

&lt;h2&gt;
  
  
  Merging the Pull Request
&lt;/h2&gt;

&lt;p&gt;Typically, the repository owner will be doing this next step. From the pull request’s page, the reviewer can look at the changes made in your branch. They can leave comments, tag your username with the @ symbol to notify you, and even comment directly on lines of code.&lt;/p&gt;

&lt;p&gt;Let’s pretend we’re the reviewers of this PR. We look through the proposed changes and we decide everything is good to go. The next step is to click the “Merge pull request” button, which should be enabled because there should not be any conflicts with the base branch. If there were conflicts, the button would be disabled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c0z0cpwht3c6a8o4e3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c0z0cpwht3c6a8o4e3m.png" width="800" height="238"&gt;&lt;/a&gt;After clicking the “Merge pull request” button, it’ll change to “Confirm merge.” Click it again to confirm and note the new message “Pull request successfully merged and closed.” We can click the “Revert” button if we need to undo this merge, but since everything is fine, let’s go ahead and delete the branch.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;**Note&lt;/em&gt;&lt;em&gt;: Some teams prefer to delete branches once they’ve been merged, others don’t. Make sure to always adhere to the repository’s norms.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Go back to your repo’s homepage (by clicking “ecs-git-tutorial” in the top right) and click the &lt;code&gt;tutorial.txt&lt;/code&gt; file. You should now see the line “This line was added from the edit-tutorial.txt branch” we just added. We’ve successfully merged our changes!&lt;/p&gt;

&lt;h3&gt;
  
  
  Resync With Main
&lt;/h3&gt;

&lt;p&gt;Back in your terminal, checkout the main branch again by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git checkout main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll get a message that says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Switched to branch 'main'
Your branch is up to date with 'origin/main'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but that’s not true. After checking out main, open tutorial.txt in a text editor. What do you notice? You’ll see that the line we added in the PR isn’t in our local copy of &lt;code&gt;main&lt;/code&gt;. What gives?&lt;/p&gt;

&lt;p&gt;Well, we actually just need to sync our local &lt;code&gt;main&lt;/code&gt; branch with the remote &lt;code&gt;main&lt;/code&gt; branch on GitHub. First, we can sync our data by running &lt;code&gt;git fetch&lt;/code&gt; which will update our local repository with notifications of any changes made to remote (&lt;strong&gt;&lt;em&gt;NOTE!&lt;/em&gt;&lt;/strong&gt; The &lt;code&gt;fetch&lt;/code&gt; command does &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; update your local branches, it only updates your repository with current information about the repo like PRs made or if your branches are behind).&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;git status&lt;/code&gt; and you should now see a message about being behind by a few commits. Mine looks like this after running the &lt;code&gt;fetch&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; git status
On branch main
Your branch is behind by 'origin/main' by 2 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

nothing to commit, working tree clean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To pull the changes from the merged PR onto our local &lt;code&gt;main&lt;/code&gt; branch, we simply have to run &lt;code&gt;git pull&lt;/code&gt;. Run that in your terminal and open the tutorial.txt file again. You should notice this time that the “This line was added from the edit-tutorial.txt branch” line is in there now.&lt;/p&gt;

&lt;p&gt;And that concludes our lesson on merging pull requests!&lt;/p&gt;

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

&lt;p&gt;This concludes part two of our professional git series. We now know how to initialize a repository, make and commit changes, make new branches, publish on GitHub, and create pull requests. That’s a ton of useful information and if your next job is anything like mine, this is stuff you will do multiple times a day, so it’s good you know how to do it now.&lt;/p&gt;

&lt;p&gt;Also, this is all the information you need to know in order to participate in open source software (OSS) on GitHub. You now have all the tools you need to start contributing to public projects (if you want to, that is)!&lt;/p&gt;

&lt;p&gt;In the next and final part of this series, we will learn rebasing and bisecting, two git commands that are not so common, but are super useful when you need them. Until next time, let me know if you have any questions by emailing me at &lt;a href="mailto:ewhiting@erikscode.space"&gt;ewhiting@erikscode.space&lt;/a&gt;, or tweet at me &lt;a href="https://twitter.com/ErikWhiting4" rel="noopener noreferrer"&gt;@ErikWhiting4&lt;/a&gt; (I just got a new Twitter, give me a follow!)&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>git</category>
    </item>
    <item>
      <title>Professional Version Control with Git: Pt 1 - The Basics</title>
      <dc:creator>Erik</dc:creator>
      <pubDate>Sat, 10 Jul 2021 19:36:26 +0000</pubDate>
      <link>https://dev.to/erikwhiting88/professional-version-control-with-git-pt-1-the-basics-3ahm</link>
      <guid>https://dev.to/erikwhiting88/professional-version-control-with-git-pt-1-the-basics-3ahm</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/erikwhiting88/professional-version-control-with-git-pt-2-collaboration-26mp"&gt;Part 2 - Collaboration&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/erikwhiting88/professional-version-control-with-git-pt-3-rebase-and-bisect-163k"&gt;Part 3 - Rebase and Bisect&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Welcome to part one of Erik’s Code Space’s first article series of 2021! In this series we’re going to learn all about version control using Git and GitHub. In this first part of the series, we’re going to talk a little about the idea of version control, then jump right in to hands-on usage. This is the kind of thing that’s going to help you right away, &lt;strong&gt;&lt;em&gt;and&lt;/em&gt;&lt;/strong&gt; it’s the sort of skill that employers are going to expect you to have. Without further ado, let’s jump right into it.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Version Control?
&lt;/h2&gt;

&lt;p&gt;In software development, version control refers to the things we do to manage and organize different versions of the projects we’re building. This &lt;em&gt;can&lt;/em&gt; mean things like maintaining release versions and old versions for your customers to use, but for most programmers, version control is about keeping a record of the changes you make to the code you’re writing. It serves 3 purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeping a record of changes and decisions made to your code&lt;/li&gt;
&lt;li&gt;Providing a safety net for experimentation&lt;/li&gt;
&lt;li&gt;Allowing collaboration on projects all over the world&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re going to get into how we can use version control to do all these things in this series. For right now, let’s talk about the different kinds of version control&lt;/p&gt;
&lt;h3&gt;
  
  
  Version Control Softwares
&lt;/h3&gt;

&lt;p&gt;There are many different products out there for you to use. Git is by far the most popular tool for version control and is the tool we’ll be using for this series because it’s free and because it’s the most likely thing you’ll use at work. There are other version control products out there that get plenty of use in the professional world such as Subversion and Mercurial. I’m not sure if these tools have niche industries or domains, but you can’t go wrong by knowing Git.&lt;/p&gt;

&lt;p&gt;Along with Git, there are two &lt;strong&gt;&lt;em&gt;major&lt;/em&gt;&lt;/strong&gt; Git servers-as-a-service: &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and &lt;a href="https://about.gitlab.com/" rel="noopener noreferrer"&gt;GitLab&lt;/a&gt;. Both have a lot of services for collaboration, continuous integration (CI), continuous deployment (CD), versioning, sharing, issue tracking, and more. For our purposes, we are going to stick with GitHub since this is the service the author knows best. However, we will &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; be using GitHub in part one of this series, so don’t worry about it for now. But, if you want to save some time, go ahead and make yourself a GitHub account so that you’re ready for part 2.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing Git
&lt;/h2&gt;

&lt;p&gt;Alright, we’re ready to get started. First we have to install Git on our computers. It’s very possible you’ve already got Git on your computer, so let’s check and see if that’s the case real quick. Open up your command line of choice and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have Git on your computer already, you will get something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git version 2.16.2.windows.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as the output. If not, you have two options depending on what operating system you’re on. For Linux and Mac users, you can simply go to the terminal and type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; sudo dnf install git-all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re on Windows, you’ll have to head over to &lt;a href="https://gitforwindows.org/" rel="noopener noreferrer"&gt;gitforwindows&lt;/a&gt; and follow the download instructions there. Don’t worry about installing any GUI programs. In my experience, Git is much more intuitive once you get used to using it from the command line than any GUI program (but if you must use one, I recommend GitHub desktop).&lt;/p&gt;

&lt;p&gt;Once you’ve installed the appropriate version for your OS, reload your terminal and type in the &lt;code&gt;git --version&lt;/code&gt; command again to make sure git is in your path. Once you’ve done that, you’re ready to start using it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Git Basic Concepts
&lt;/h2&gt;

&lt;p&gt;We use git to keep a record of what we’ve done in our software projects so that we can see every change we’ve ever made and keep a running log of what we did. Starting out, it’s best to think of git as a tool for keeping a timeline. Remember those timeline graphs in your 6th grade history textbooks? They looked kind of like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5brp58tjemfbuqripoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5brp58tjemfbuqripoa.png" alt="Sample Timelines - Timeline Maker Pro | The Ultimate Timeline Software |  History timeline template, Timeline example, History timeline" width="800" height="562"&gt;&lt;/a&gt;See how there’s a line depicting time, and an arrow and blurb about every significant event that happened during this (presumably made up) company’s history? Git creates something like this, but for our software projects. The solid line is kind of like Git’s “branch” and the messages along the line are a lot like Git’s “commits.”&lt;/p&gt;

&lt;p&gt;Basically, we start off by initializing a Git &lt;strong&gt;&lt;em&gt;repository&lt;/em&gt;&lt;/strong&gt;. In the company timeline metaphor, the repository is the actual company. It’s the body of code of which we are keeping a running record.&lt;/p&gt;

&lt;p&gt;Then, you start working on the repository. You might kick things off by creating a &lt;code&gt;getting_started.py&lt;/code&gt; Python script. You begin by writing the code for that file until you get to a reasonable stopping point. You look over the code you wrote and, if everything looks good, you decide to &lt;strong&gt;&lt;em&gt;commit&lt;/em&gt;&lt;/strong&gt; the file to the repository.&lt;/p&gt;

&lt;p&gt;To commit the file, you also have to write a small message. Something like “Wrote proof of concept script.” Once you make the commit, that message becomes the first bit of text on the timeline of your software project. That timeline is called a &lt;strong&gt;&lt;em&gt;branch&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At pretty much any given time, you are at the right-most part of the branch you’re working on. Every commit you make adds another event to the timeline. Luckily, we can spawn branches off of other branches. For example, on your current timeline, you may decide you want to experiment with creating a new file like &lt;code&gt;file_two.py&lt;/code&gt; but it’s not quite ready to be an official part of the project history. In this case you’ll create a new branch off of the official branch (often named something like main, master, or trunk). In this way, you can experiment with an alternate timeline. If you like the work you did on the new branch, you can then &lt;strong&gt;&lt;em&gt;merge&lt;/em&gt;&lt;/strong&gt; that branch into main. This will make all of the work you did on the alternate branch part of the official history of main.&lt;/p&gt;

&lt;p&gt;These are the core concepts behind how Git works. There’s a lot more to it but don’t worry, We’re about to get hands-on with this tool and it’ll all make a lot more sense.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initializing Your Repository
&lt;/h3&gt;

&lt;p&gt;Go ahead and open up your terminal of choice, whether it’s bash, DOS, PowerShell, or something else. Find your way into a folder that you use for projects and make a new directory called &lt;code&gt;git_project&lt;/code&gt; and cd into it. I’m doing this on PowerShell, so it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; mkdir git_project
&amp;gt; cd git_project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we’re going to initialize our repository. This basically means we’re telling Git that everything in this directory is a project that we want to keep track of. We’re going to name our primary branch “main,” so the command to do that is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git init -b main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get a message saying “Initialized empty Git repository in , and if you look, there’s a new directory here called &lt;code&gt;.git&lt;/code&gt;. Don’t mess with it, I just want you to know that it’s supposed to be there. Also, the directory from which you ran this command is now the project’s &lt;strong&gt;&lt;em&gt;root&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Files
&lt;/h3&gt;

&lt;p&gt;Ok, now that we’ve got our repository initiated, it’s time to start writing some code for Git to track. Let’s create a Python file called &lt;code&gt;getting_started.py&lt;/code&gt;. Since we’re in the command line, I like to use commands to do this, but you can do it from explorer, or an IDE, or anything else you want. Either way, create the file and open it in your editor. In Linux I use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; touch getting_started.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or in PowerShell on Windows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; echo '' &amp;gt; getting_started.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since this isn’t a Python tutorial, we’ll keep the code we write to a minimum and very simple. We’ll write a very short function called &lt;code&gt;greet&lt;/code&gt; that looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def greet(name):
  return f'Hello, {name}!'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s head back over to our terminal. Type in the command &lt;code&gt;git status&lt;/code&gt; and take note of the output. This is what mine looks like, yours should be fairly similar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git status
On branch main

No commits yet

Untracked files:
  (use "git add &amp;lt;file&amp;gt;..." to include in what will be committed)
        getting_started.py

nothing added to commit but untracked files present (use "git add" to track)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;getting_started.py&lt;/code&gt; is listed under “untracked files.” This is because we haven’t yet told Git that this is a file we want to keep track of. In order to do this, we have to &lt;strong&gt;&lt;em&gt;add&lt;/em&gt;&lt;/strong&gt; the file to the repository. The command to do so is probably exactly what you think:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git add getting_started.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type in the above command and hit enter. We’ve now officially added &lt;code&gt;getting_started.py&lt;/code&gt; to the repository and Git will track it’s changes from now on. Go ahead and run &lt;code&gt;git status&lt;/code&gt; again and note the new output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached &amp;lt;file&amp;gt;..." to unstage)
        new file:   getting_started.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See now that &lt;code&gt;getting_started.py&lt;/code&gt; is listed under “Changes to be committed.” This is a pretty nice segue into our next command, &lt;code&gt;commit&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Committing Changes
&lt;/h3&gt;

&lt;p&gt;We’ve now decided that we’re happy enough with our &lt;code&gt;greet&lt;/code&gt; function in the &lt;code&gt;getting_started&lt;/code&gt; script. It’s time to commit these changes, or make them an official part of this project’s history. Like I said earlier, we’ll have to come up with a short message to describe what we’ve done. All we’ve really done was create the &lt;code&gt;greet&lt;/code&gt; function, so let’s go with that. The command to commit our changes with this message is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git commit -m "Create greet function"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will get some output about how many files were changed and some other stuff that you don’t really need to pay much attention to for now. Let’s see what happens when we run the status command again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git status
On branch main
nothing to commit, working tree clean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In committing our work, we’ve made this file and function an official part of the project’s history. As such, there are no “changes” to commit when we check the status of the repository. Let’s go ahead and make a few more changes to &lt;code&gt;getting_started.py&lt;/code&gt; though, I want to add a new function called &lt;code&gt;double_this&lt;/code&gt;. The function will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def double_this(number):
  return number * 2

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

&lt;/div&gt;



&lt;p&gt;Make sure to save your changes and then head back over to the terminal. Let’s run the status command again and see what our repository looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git status
On branch main
Changes not staged for commit:
  (use "git add &amp;lt;file&amp;gt;..." to update what will be committed)
  (use "git restore &amp;lt;file&amp;gt;..." to discard changes in working directory)
        modified:   getting_started.py

no changes added to commit (use "git add" and/or "git commit -a")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice this time that &lt;code&gt;getting_started.py&lt;/code&gt; is not listed under “Untracked files” but “Changes not staged for commit.” That’s because whenever we change a file, we have to run &lt;code&gt;git add&lt;/code&gt; again to &lt;strong&gt;&lt;em&gt;stage&lt;/em&gt;&lt;/strong&gt; the changes before we can commit them. In other words, once we’re ready to commit our changes, we have to first run the &lt;code&gt;add&lt;/code&gt; command and then the &lt;code&gt;commit&lt;/code&gt; command again. Don’t run the following commands (I’m about to show you a better way) but this is what they would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git add getting_started.py
&amp;gt; git commit -m "Added double_this function"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of the time, however, you don’t stage changes until you’re ready to commit them. Because of this, there’s a short hand we use to both stage the changes and commit them at the same time, by passing the letter &lt;code&gt;a&lt;/code&gt; as a command line argument in your &lt;code&gt;commit&lt;/code&gt; command. The above example can be condensed into a single command that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git commit -am "Added double_this function"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this command, we simultaneously staged our changes and committed them. (Note: This will not work for “untracked files” which you have to manually add to the repository with &lt;code&gt;git add&lt;/code&gt;) Personally, this is the way I do commits 99% of the time. Now, “Added &lt;code&gt;double_this&lt;/code&gt; function” is officially part of our project’s history. But what is this history I keep talking about? Well, it’s really more of a log, let’s talk about it:&lt;/p&gt;

&lt;h3&gt;
  
  
  Seeing Your Project’s History
&lt;/h3&gt;

&lt;p&gt;Remember how I said the Git repository is like a timeline for your project? Well, we can view that timeline with &lt;code&gt;git log&lt;/code&gt;, which can show us our entire history, take a look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git log
commit bfae576bca086e682eae6ca0a7b12d23621234a8 (HEAD -&amp;gt; main)
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 20:01:47 2021 -0500

    Added double_this function

commit 47308246e7a8dbfe6fd3b4361f28c4a1e6643f79
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 19:50:01 2021 -0500

    Create greet function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s a few things that might look a little foreign in this log, so lets go through each one at a time. First, we see “&lt;code&gt;commit&lt;/code&gt;” with a hash. This is, unsurprisingly, the commit hash. It’s unique to your whole project and there are commands we’ll learn later in which you will use this hash. Well, you’ll actually only use the first few characters of the hash as Git is usually smart enough to figure out the rest.&lt;/p&gt;

&lt;p&gt;Next, you see “Author.” This is your Git username and you can see it by running &lt;code&gt;git config user.name&lt;/code&gt; or set it by running &lt;code&gt;git config --global user.name "new-name"&lt;/code&gt; if you need to. The same goes with the email address that follows.&lt;/p&gt;

&lt;p&gt;The “Date” field is obvious enough, but notice that the next line is the commit message we wrote earlier. This is what I mean when I say Git keeps a history of your project. The Git log is important for several reasons, and it’s imperative that you write good commit messages. Many times, the Git log is used by other members on your team to see what work was done most recently. Other times, people scrolling through your project might read through it to get a feel for what your project is about and how you work.&lt;/p&gt;

&lt;p&gt;Most importantly though, it’s a way for you to look back on your project and see what changes you made at any given point. One day you might be staring at a weird piece of code and think to yourself “why in the world did I do that?” Using Git, you can actually go back and see when you wrote that code, what code was there before, and your own commit message. This is a very useful tool and you never know when it might come in handy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Undoing Changes
&lt;/h3&gt;

&lt;p&gt;Let’s talk about another thing Git helps us with: experimentation. Sometimes, you have a big idea and you want to see if you can make it work in your project. You don’t want to mess up the project though, so you make sure you start from a clean commit (i.e., no outstanding changes, staged or otherwise). At some point, you decide that the changes you wanted to make are either too complicated or aren’t going to work. With Git, you can blow everything away, no matter what you changed, and go back to exactly the way things were before you started. Let’s see this idea in action.&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;getting_started.py&lt;/code&gt; script again and lets mess with the &lt;code&gt;double_this&lt;/code&gt; function by making it use a float instead of an integer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def double_this(number):
  return number * &amp;lt;strong&amp;gt;2.0&amp;lt;/strong&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save your changes and go back to the terminal, run &lt;code&gt;git status&lt;/code&gt; to make sure &lt;code&gt;getting_started.py&lt;/code&gt; is listed as “Changes not staged for commit”&lt;/p&gt;

&lt;p&gt;Say that now that we’ve thought about it, we like doubling with the integer instead of the float. We &lt;em&gt;could&lt;/em&gt; go back and just press Ctrl+z until things go back to the way they were, but as changes start to get bigger, approaches like that don’t work. Luckily, there’s a single line command in Git to undo all the unstaged changes, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git checkout getting_started.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now go back to &lt;code&gt;getting_started.py&lt;/code&gt; in your code editor. Notice anything? The &lt;code&gt;double_this&lt;/code&gt; function should have returned to it’s original state. Isn’t that convenient? Even if you have multiple changes spanning across several files, as long as those files are tracked, the &lt;code&gt;checkout&lt;/code&gt; command will return them to their most recent commit.&lt;/p&gt;

&lt;p&gt;By the way, you can apply git commands like &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;checkout&lt;/code&gt; to multiple files instead of running one command per file. Most of the time, I just run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git add .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to stage &lt;strong&gt;all&lt;/strong&gt; changes at once. You can also specify which files you want the operation to be run on in a single line like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git checkout file1.txt file2.py file3.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, you can also use regex-like commands. For example, say you want to stage changes made to any Ruby files, you’d write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git add *.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reverting Changes
&lt;/h3&gt;

&lt;p&gt;Sometimes you decide that a change you made was entirely wrong, but you’ve already committed it. The &lt;code&gt;checkout&lt;/code&gt; command won’t work for undoing those kinds of changes, but there &lt;em&gt;is&lt;/em&gt; an option, it’s called &lt;strong&gt;&lt;em&gt;revert&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Reverting our changes means undoing an entire commit. Let’s say that now we don’t want the &lt;code&gt;double_this&lt;/code&gt; function in our script &lt;em&gt;at all&lt;/em&gt;. Sure, we could delete it manually and make a new commit with the message “deleted double_this.” But if we wanted to surgically remove all the work we did, we could use the revert command. The first thing you have to do is find the hash of the commit you want to undo, remember that we get that from the &lt;code&gt;log&lt;/code&gt; command. Check it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git log
commit &amp;lt;strong&amp;gt;bfae576bca086e682eae6ca0a7b12d23621234a8&amp;lt;/strong&amp;gt; (HEAD -&amp;gt; main)
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 20:01:47 2021 -0500

    Added double_this function

commit 47308246e7a8dbfe6fd3b4361f28c4a1e6643f79
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 19:50:01 2021 -0500

    Create greet function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to revert the commit with the message “Added double_this function.” Find the commit hash, for me it’s “bfae576bca086e682eae6ca0a7b12d23621234a8” but it will be different for you. To revert, run the following command, but replace my hash with yours (note, you can use just the first 5 or 6 characters of your commit hash):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git revert --no-edit bfae576bca086e682eae6ca0a7b12d23621234a8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And press enter. Go back to your code editor and note that &lt;code&gt;double_this&lt;/code&gt; is now gone. Go back to the terminal and run &lt;code&gt;git log&lt;/code&gt; to see what the history looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git log
commit 275c72742cf806d2517661d5ae8f2d9e516efed2
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 20:51:56 2021 -0500

    &amp;lt;strong&amp;gt;Revert "Added double_this function"

    This reverts commit bfae576bca086e682eae6ca0a7b12d23621234a8.&amp;lt;/strong&amp;gt;

commit bfae576bca086e682eae6ca0a7b12d23621234a8
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 20:01:47 2021 -0500

    Added double_this function

commit 47308246e7a8dbfe6fd3b4361f28c4a1e6643f79
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 19:50:01 2021 -0500

    Create greet function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we still keep the history. We have “Added double_this function” in the Git log, but we also have “Revert ‘Added double_this function.'” The “Revert …” commit message is actually the default commit message when running the &lt;code&gt;revert&lt;/code&gt; command, which is what we get when we pass the &lt;code&gt;--no-edit&lt;/code&gt; flag. If you wanted to write your own message, leave that flag out. Git will ask you what program you want to use to write your commit message (I usually use notepad++ on Windows and Nano on Linux). Once you’re done editing the file, close the program and the commit will be made.&lt;/p&gt;

&lt;h3&gt;
  
  
  Those are the basics!
&lt;/h3&gt;

&lt;p&gt;You now know how to initialize a repository, track files, commit changes, undo changes, and revert to a previous commit. That concludes the basic ideas behind Git operations, now let’s dive into branching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git Branches
&lt;/h2&gt;

&lt;p&gt;One of the best things about Git is branching. It lets us essentially live multiple histories at a single time without disturbing the &lt;em&gt;true&lt;/em&gt; history until we’re ready. We can experiment, test out new features without changing a production system, and collaborate with other developers.&lt;/p&gt;

&lt;p&gt;To illustrate the most typical use of branching, I will describe how I typically handle changes to a website I maintain. It’s a pretty simple website with the company’s name on it, and a few pages describing their team, a catalogue of their products, and a signup form for their mailing list. Let’s imagine someone finds a bug in the website, like the the form isn’t saving the person’s name properly.&lt;/p&gt;

&lt;p&gt;Instead of disrupting operations by poking around and the company’s public facing website, I make a new branch off the &lt;code&gt;main&lt;/code&gt; branch so that I can investigate the source of the bug and fix it. When I make a new branch from the main one, I essentially copy it: everything from the code to the commit history. But as I make changes to the new branch, the main one stays as it is. I can even switch back to it if a new, more important thing needs addressing, and then switch back to my other work when that’s done.&lt;/p&gt;

&lt;p&gt;When I’m done investigating the source of the signup form bug and apply the changes, I then &lt;strong&gt;&lt;em&gt;merge&lt;/em&gt;&lt;/strong&gt; the changes onto the main branch. That’s when everything I’ve done on the new branch becomes one with the main branch. Let’s go ahead and see this in action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making a New Branch
&lt;/h3&gt;

&lt;p&gt;Within our &lt;code&gt;git_project&lt;/code&gt; repository, we decide we want to make a new function once again, but we don’t want it to be on the main branch until we’re done with it. First, what we do is create a new branch with the &lt;code&gt;branch&lt;/code&gt; command. Then we &lt;strong&gt;&lt;em&gt;checkout&lt;/em&gt;&lt;/strong&gt; that branch so that the work we do gets tracked in the new branch’s history rather than the main one.&lt;/p&gt;

&lt;p&gt;First, go to your terminal and see what branch we’re on by typing &lt;code&gt;git branch&lt;/code&gt;. The output should have the work “main” in green with an asterisk next to it. The asterisk indicates which branch you’re on (being “on” a branch means that the changes you make are being tracked and recorded in that branch’s history). Let’s make a new branch with the &lt;code&gt;branch&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git branch add-new-method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates the branch, now we need to &lt;strong&gt;&lt;em&gt;checkout&lt;/em&gt;&lt;/strong&gt; the branch. Once we run the next command, we’ll be on the &lt;code&gt;add-new-method&lt;/code&gt; branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git checkout add-new-method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the terminal should output “&lt;code&gt;Switched to branch 'add-new-method'&lt;/code&gt;“. In the future, if you would like to create a branch and check it out in one command, you use the &lt;code&gt;checkout&lt;/code&gt; command with a &lt;code&gt;-b&lt;/code&gt; argument like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git checkout -b add-new-method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, so now that we’re on the &lt;code&gt;add-new-method&lt;/code&gt; branch, I want you to see something. In the terminal, run &lt;code&gt;git log&lt;/code&gt; and see the output. It should be the exact same as it was last time you looked at it on the &lt;code&gt;main&lt;/code&gt; branch. In fact, until we commit anything in either branch, their log will be the same.&lt;/p&gt;

&lt;p&gt;Let’s go ahead and add some code. Let’s make a new method called &lt;code&gt;triple_this&lt;/code&gt; which will do pretty much what you’re probably expecting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def triple_this(number):
  return 3 * number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s go ahead and commit these changes as well. In the terminal type the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git commit -am "Add triple this function"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we’ve committed this work to &lt;em&gt;this branch’s&lt;/em&gt; history. Check out the output from &lt;code&gt;git log&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;commit 65ed67a53aeb94b27865e401cc456e6b2b33bf2a (HEAD -&amp;gt; add-new-method)
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 22:55:58 2021 -0500

    Add triple_this function

commit 0ea7a943b604f5efebaecb7e2ede33cf00cf7de2 (main)
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 20:54:16 2021 -0500

    Revert "Added double this"

    This reverts commit ae2a9fe016ab88a07dc6b06b9ca4417dd3f0933e.

commit ae2a9fe016ab88a07dc6b06b9ca4417dd3f0933e
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 20:53:37 2021 -0500

    Added double this

...
(truncated)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commit about adding the &lt;code&gt;triple_this&lt;/code&gt; function is in this branch’s history. Let’s switch back to the &lt;code&gt;main&lt;/code&gt; branch, this is going to make it all make more sense. In the terminal type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git checkout main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First of all, go look at the &lt;code&gt;getting_started.py&lt;/code&gt; script and notice that the &lt;code&gt;triple_this&lt;/code&gt; function is not there. That’s because that work was on the &lt;code&gt;add-new-method&lt;/code&gt; branch, not the main one. Additionally, run &lt;code&gt;git log&lt;/code&gt; again and notice that the commit for &lt;code&gt;triple_this&lt;/code&gt; isn’t in there.&lt;/p&gt;

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

&lt;p&gt;To illustrate another point I want to make later, let’s make yet another branch. This time, we’re going to edit the &lt;code&gt;greet&lt;/code&gt; method. So in the terminal, make sure you’re on the &lt;code&gt;main&lt;/code&gt; branch by typing &lt;code&gt;git branch&lt;/code&gt; and ensuring &lt;code&gt;main&lt;/code&gt; is starred. Now, type in the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git checkout -b edit-greet-method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re now on the &lt;code&gt;edit-greet-method&lt;/code&gt; branch, so head into the &lt;code&gt;getting_started.py&lt;/code&gt; script and set the &lt;code&gt;greet&lt;/code&gt; method to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def greet(name):
  return f'What\'s up, {name}?'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s go ahead and commit this change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git commit -am "Edit greet function"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once again, check the log and notice that the only commit message after our revert of the “Added double this” commit is the one we just made: “Edit greet function.” Switch back to the &lt;code&gt;main&lt;/code&gt; branch by typing &lt;code&gt;git checkout main&lt;/code&gt; in the terminal and once again note that the most recent commit message in the log is the one about reverting the &lt;code&gt;double_this&lt;/code&gt; method. Also note that in the &lt;code&gt;getting_started.py&lt;/code&gt; script, the method is how we left it, with the “Hello” greeting instead of “What’s up.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Merging Branches
&lt;/h3&gt;

&lt;p&gt;Ok, now that we’ve made changes on two different branches and we think we’re happy with them, it’s time to merge those changes into our &lt;code&gt;main&lt;/code&gt; branch and unifying the histories. First, make sure you’re on the &lt;code&gt;main&lt;/code&gt; branch. First, we’re going to merge in the &lt;code&gt;edit-greet-method&lt;/code&gt;. In the terminal type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git merge edit-greet-method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll get some output about fast-forwarding and how many files were changed. Look at the script and notice that the &lt;code&gt;greet&lt;/code&gt; function is now using the “What’s up” greeting instead of “Hello.” In the terminal, check out the log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git log
commit ad0ca3092e6e49a86d8f228d2b9e7f39b8a559ca (HEAD -&amp;gt; main, edit-greet-method)
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 23:08:03 2021 -0500

    Edit greet function

commit 0ea7a943b604f5efebaecb7e2ede33cf00cf7de2
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 20:54:16 2021 -0500

    Revert "Added double this"

    This reverts commit ae2a9fe016ab88a07dc6b06b9ca4417dd3f0933e.

commit ae2a9fe016ab88a07dc6b06b9ca4417dd3f0933e
Author: erik-whiting &amp;lt;erik@erikwhiting.com&amp;gt;
Date:   Thu Mar 25 20:53:37 2021 -0500

    Added double this
...
(truncated)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we see that the commit history (equivalent to the notes from our timeline example from earlier) from the &lt;code&gt;edit-greet-method&lt;/code&gt; branch is now unified–or &lt;strong&gt;&lt;em&gt;merged&lt;/em&gt;&lt;/strong&gt;–with the commit history of &lt;code&gt;main&lt;/code&gt;. Essentially, we’ve made the work we did on the &lt;code&gt;edit-greet-method&lt;/code&gt; branch part of the official history.&lt;/p&gt;

&lt;p&gt;Let’s go ahead and do the same for the &lt;code&gt;add-new-method&lt;/code&gt; branch. We created that branch before we created the &lt;code&gt;edit-greet-method&lt;/code&gt; branch though, do you think that’s going to cause problems? Let’s find out. Run the following in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; git merge add-new-method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will probably get output similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warning: Cannot merge binary files: getting_started.py (HEAD vs. add-new-method)
Auto-merging getting_started.py
CONFLICT (content): Merge conflict in getting_started.py
Automatic merge failed; fix conflicts and then commit the result.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uh oh, what happened? There are merge conflicts. This is because when we created the &lt;code&gt;add-new-method&lt;/code&gt; branch, the &lt;code&gt;getting_started.py&lt;/code&gt; file’s git history was one way, but when we merged &lt;code&gt;edit-greet-method&lt;/code&gt; into the &lt;code&gt;main&lt;/code&gt; branch, that history was updated. This means that &lt;code&gt;add-new-method&lt;/code&gt; is now out of sync with the &lt;code&gt;main&lt;/code&gt; branch, causing a &lt;strong&gt;&lt;em&gt;merge conflict&lt;/em&gt;&lt;/strong&gt;. There’s an easy way to fix this though, don’t worry.&lt;/p&gt;

&lt;p&gt;What you’ll have to do is go into your IDE, or whatever you were writing your code with, and find where the conflicts are. If you’re using an IDE like vscode or PyCharm or anything like that, the changes will be highlighted very obviously. Otherwise, you’ll have to look out for something that says&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
  return f'What\s up, {name}'
=======
  return 'Hello, {name}'

def triple_this(number):
  return 3 * number
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; add-new-method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here, you basically pick which versions you want to keep, either incoming, current, or both. You can do this by strategically deleting what you want to keep and what you want to throw out. It can get kind of tedious, but with an IDE, usually there’s a button you can press to accept one or the other.&lt;/p&gt;

&lt;p&gt;In our case, we want to not only delete all the &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt; type of things we don’t need, but also, we want to delete the old return method from the &lt;code&gt;greet&lt;/code&gt; function. In other words, your final script should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def greet(name):
  return f'What\s up, {name}!'

def triple_this(number):
  return 3 * number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you’ve got that, go ahead and run your commit message, and check the history. Voila!&lt;/p&gt;

&lt;p&gt;I should note that these merge conflicts only happened because we were using the same file. In real-world systems when two people are working on the same repository, it’s unlikely they’ll be working on the same file. Merge conflicts only occur when the same file with two different histories are trying to be committed, files whose histories haven’t changed from branch to branch will not throw conflicts like this.&lt;/p&gt;

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

&lt;p&gt;This concludes part one of our professional git series. In part 2 we’re going to learn about publishing, cloning, and making pull requests on GitHub. Part 3 will cover some more advanced topics such as rebase and bisect. This is really good information that is very important for leveling up your coding skills, so stay tuned!&lt;/p&gt;

</description>
      <category>git</category>
      <category>svc</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
