<?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: David Adamo Jr.</title>
    <description>The latest articles on DEV Community by David Adamo Jr. (@davidadamojr).</description>
    <link>https://dev.to/davidadamojr</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%2F271926%2F7165afb5-4c50-4378-9463-6c76b8a43da8.png</url>
      <title>DEV Community: David Adamo Jr.</title>
      <link>https://dev.to/davidadamojr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidadamojr"/>
    <language>en</language>
    <item>
      <title>Texas Sharpshooters and Test-Driven Development (TDD)</title>
      <dc:creator>David Adamo Jr.</dc:creator>
      <pubDate>Fri, 09 Feb 2024 02:49:52 +0000</pubDate>
      <link>https://dev.to/davidadamojr/texas-sharpshooters-and-test-driven-development-tdd-3dgb</link>
      <guid>https://dev.to/davidadamojr/texas-sharpshooters-and-test-driven-development-tdd-3dgb</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover image taken from an illustration by Dirk-Jan Hoek&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I recently learned about a logical fallacy called &lt;a href="https://en.wikipedia.org/wiki/Texas_sharpshooter_fallacy"&gt;The Texas Sharpshooter fallacy&lt;/a&gt;. The first thought that crossed my mind when I first read about it was, "What does Texas have to do with any of this?". I still don't have a convincing answer for that one.&lt;/p&gt;

&lt;p&gt;More importantly, the second thought that crossed my mind was how The Texas Sharpshooter fallacy clearly expresses one of the ways I think about &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;Test-Driven Development (TDD)&lt;/a&gt;. This blog post describes how TDD may reduce your likelihood of writing tests like a Texas Sharpshooter.&lt;/p&gt;

&lt;p&gt;So what is this Texas Sharpshooter fallacy anyway?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Texas Sharpshooter Fallacy
&lt;/h2&gt;

&lt;p&gt;The Texas Sharpshooter Fallacy occurs when you find patterns to fit something you've already assumed to be true or correct. The name comes from an analogy where a shooter fires shots at a barn door and then paints targets around the bullet holes to create the false impression of being an excellent marksman.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test-Driven Development (TDD)
&lt;/h2&gt;

&lt;p&gt;TDD is a software development approach that encourages you to write tests before writing the code that makes the tests pass. It revolves around a red-green-refactor cycle that comprises the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write a test that fails (red)&lt;/li&gt;
&lt;li&gt;Write the minimal amount of code that makes the test pass (green)&lt;/li&gt;
&lt;li&gt;Refactor the code to meet quality standards while ensuring that tests still pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TDD has several benefits. One often touted benefit of TDD is that it helps you make better design decisions. Since TDD demands that you write tests first before writing the corresponding code, it forces you to always start by thinking through the design and expected behavior of the code you're going to write. This upfront focus on design and behavior often results in better software design and architecture relative to a test-after approach where you dive straight into writing code before writing corresponding tests. &lt;/p&gt;

&lt;h2&gt;
  
  
  What does the Texas Sharpshooter Fallacy have to do with TDD?
&lt;/h2&gt;

&lt;p&gt;The positive influence that TDD can have on software design is generally well-known. A less popular discussion is the direct positive influence that TDD could have on your tests. Remember that tests should verify that your code behaves the way it is supposed to, as defined by software requirements. Sometimes, you may end up writing code that seems acceptable to you without realizing that there is some difference between what your code does and what it is supposed to do. When you write code before writing tests, you are more likely to write tests that verify what the code does instead of what it is supposed to do. Writing code before tests makes it too easy for you to mold your tests around flawed code without realizing it. In many cases, you'll end up with tests that merely confirm flawed behavior. &lt;/p&gt;

&lt;p&gt;TDD forces you to start by writing a failing test based on the expected behavior of the code you'll eventually write. Note that the code that the failing test seeks to verify does not exist at this point, so you are primarily focused on the expected behavior, and there is nothing around which to (incorrectly) mold your tests. In other words, your tests written as part of the TDD cycle are much less likely to be biased by code you've already written because the code does not exist yet. &lt;/p&gt;

&lt;p&gt;In the context of the Texas Sharpshooter analogy, your code represents the shots you've fired at the barn door, and your tests are the targets that those shots are meant to hit. Writing your code before writing your tests is like firing shots at the barn door before painting the targets. When you write your code first (i.e., fire shots) and then write the tests afterward (i.e, paint targets), it is too easy to start writing tests that are influenced ONLY by the current behavior of the code you've just written, even when that behavior is not what you intended or what the software requirements demand. If you are not careful, writing tests after writing your code will turn you into a "Texas Sharpshooter". And it's going to feel great. After all, your shots will almost always hit the target when you shoot first and paint targets around the bullet holes afterward.  &lt;/p&gt;

&lt;p&gt;Many software developers (including me) tend to write tests after writing implementation code but do not always realize that they are sharpshooters painting targets around problematic code. TDD encourages you to write tests BEFORE writing the code that makes the tests pass. Therefore, if you want to avoid being a "sharpshooter", try TDD.&lt;/p&gt;

</description>
      <category>testdrivendevelopment</category>
      <category>softwareengineering</category>
      <category>softwaretesting</category>
    </item>
    <item>
      <title>Avoid Fakers in Unit Tests</title>
      <dc:creator>David Adamo Jr.</dc:creator>
      <pubDate>Thu, 08 Feb 2024 04:03:02 +0000</pubDate>
      <link>https://dev.to/davidadamojr/avoid-fakers-in-unit-tests-53h9</link>
      <guid>https://dev.to/davidadamojr/avoid-fakers-in-unit-tests-53h9</guid>
      <description>&lt;p&gt;In your unit and integration tests, avoid using tools that automatically generate test input data. Unless you are &lt;a href="https://en.wikipedia.org/wiki/Fuzzing"&gt;fuzz testing&lt;/a&gt; or your goal is to create &lt;a href="https://github.com/STAR-RG/practical_testing_book/blob/master/testgeneration/propertybased.ipynb"&gt;property-based tests&lt;/a&gt;, these test data generators (a.k.a. fakers) are likely to do more harm than good in the long run because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Your tests will become much slower than they should be. The computational cost of randomization and data generation adds up much quicker than you might think. Slow tests are productivity poison.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By using fakers in your tests, you increase the likelihood of flakiness due to randomized data. Your future self will have a tough time figuring out why a specific test failed. Tests should be repeatable and deterministic, with input values that stay the same each time you execute them.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is often better to explicitly specify your test inputs. If you have to use a faker in your tests, make sure it always generates the same test inputs each time your tests are executed. You can do this by configuring your faker with a random seed.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Duplication over Abstraction in Unit Tests</title>
      <dc:creator>David Adamo Jr.</dc:creator>
      <pubDate>Sun, 26 Feb 2023 19:09:17 +0000</pubDate>
      <link>https://dev.to/davidadamojr/duplication-over-abstraction-in-unit-tests-1hf2</link>
      <guid>https://dev.to/davidadamojr/duplication-over-abstraction-in-unit-tests-1hf2</guid>
      <description>&lt;p&gt;One of the first things you learn as a software engineer is to avoid code duplication whenever possible. But this same learned aversion to duplication is what causes many software engineers to fill their unit tests with logic and abstractions that cause the tests to become unreliable. &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%2Fgexwj52mrf0dslggfa6d.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%2Fgexwj52mrf0dslggfa6d.png" alt="Scale from duplication to abstraction" width="800" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On a scale from duplication to abstraction, your code and its corresponding unit tests should almost never be on the same level. Unit tests are not the place for clever logic, abstractions, and code reuse. Logic and abstractions eventually cause your unit tests to become fragile and difficult to understand. If you're starting to feel like your unit tests need unit tests, then you're probably doing it wrong.&lt;/p&gt;

&lt;p&gt;In your production code, it often makes sense to treat duplication like an enemy to be vanquished everywhere it rears its ugly head. But you're much better off treating duplication like a friend in your unit tests. In other words, while you favor abstraction over duplication in your code, you should simultaneously favor duplication over abstraction in your unit tests.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>What does bad code look like?</title>
      <dc:creator>David Adamo Jr.</dc:creator>
      <pubDate>Mon, 30 Jan 2023 18:40:21 +0000</pubDate>
      <link>https://dev.to/davidadamojr/what-does-bad-code-look-like-4gd2</link>
      <guid>https://dev.to/davidadamojr/what-does-bad-code-look-like-4gd2</guid>
      <description>&lt;p&gt;What does bad code look like? Well, code that does not do what it should is probably bad by default. Not much else to say about this one.&lt;/p&gt;

&lt;p&gt;Beyond that, it is probably easier and more interesting to think of bad code in terms of what it feels like. Most of the bad code I've seen tends to fall into one of three categories.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easy to understand, difficult to change
&lt;/h2&gt;

&lt;p&gt;Working with this kind of code initially feels pleasant, but could quickly devolve into a terrifying and never-ending game of Jenga. Code like this is common among new programmers and could actually be useful in some contexts. In search of growth and perfection, too many software engineers eventually lose their tactical ability to write this kind of "bad" code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Difficult to understand, but easy to change once you get around to understanding it
&lt;/h2&gt;

&lt;p&gt;Working with this kind of code feels like a constantly swirling mix of confusion, surprise, and sudden enlightenment. This kind of code is common among experienced software engineers who have their heads full of useful principles, design patterns, and other "best practices". I've had to fight my way out of writing this kind of code more times than I can count.&lt;/p&gt;

&lt;h2&gt;
  
  
  Difficult to understand, difficult to change
&lt;/h2&gt;

&lt;p&gt;This is just the worst! Avoid like the plague.&lt;/p&gt;

&lt;p&gt;This kind of code feels like a terrifying nightmare that continues when you wake up and when you go back to sleep. I'm not sure how one ends up here, but this is certainly not what you want your code to feel like for anyone who touches it.&lt;/p&gt;

&lt;p&gt;You'll probably end up with this kind of code when you apply design patterns, design principles, programming paradigms, and/or complex architectures without understanding why these things exist and when to use them.&lt;/p&gt;




&lt;p&gt;One of the most elusive aspects of your job as a software engineer is to figure out how to produce code that is both easy to change and easy to understand. Producing such code is not easy, but it is typically the best way to build software that retains its value over time.&lt;/p&gt;

</description>
      <category>crypto</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>offers</category>
    </item>
    <item>
      <title>Are your Tests Necessary and Useful?</title>
      <dc:creator>David Adamo Jr.</dc:creator>
      <pubDate>Wed, 25 May 2022 06:05:20 +0000</pubDate>
      <link>https://dev.to/davidadamojr/are-your-tests-necessary-and-useful-4b2h</link>
      <guid>https://dev.to/davidadamojr/are-your-tests-necessary-and-useful-4b2h</guid>
      <description>&lt;p&gt;Some automated tests are unnecessary or problematic. &lt;/p&gt;

&lt;p&gt;For each automated test you write, ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Does this test offer any additional test coverage that is not already addressed by some other existing test?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Which defect(s) do I expect this test to find or prevent?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When this test fails, would I be able to easily determine what went wrong based on the test execution report?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can I reduce the scope of this test so that it integrates fewer components during its execution?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Am I testing a private method directly? If so, can I modify my test or refactor my code and test through a public method instead?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each test should exist for a good reason, and not merely to tick a box in a checklist. The effectiveness of your testing is dictated primarily by the quality of the tests you have. The number of tests that you do or do not have matters much less than you think. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>4 Job Search Tips for New Software Engineers</title>
      <dc:creator>David Adamo Jr.</dc:creator>
      <pubDate>Wed, 25 May 2022 06:02:10 +0000</pubDate>
      <link>https://dev.to/davidadamojr/job-search-tips-for-new-software-engineers-3h</link>
      <guid>https://dev.to/davidadamojr/job-search-tips-for-new-software-engineers-3h</guid>
      <description>&lt;p&gt;Entering the job market as a new Software Engineer can be challenging. Here are some job search tips for new software engineers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Take LinkedIn Seriously
&lt;/h1&gt;

&lt;p&gt;Fill out your LinkedIn profile as best you can.&lt;/p&gt;

&lt;p&gt;I have applied directly to many jobs outside of LinkedIn. However, all the jobs I have received and accepted so far, except one, originated from my LinkedIn profile.&lt;/p&gt;

&lt;h1&gt;
  
  
  Avoid Consulting Companies
&lt;/h1&gt;

&lt;p&gt;For your first job, avoid consulting companies if you can. Get a job at a company that is building and selling its own software products.&lt;/p&gt;

&lt;p&gt;Many consulting companies move people between customer projects frequently. This project instability often creates an unfavorable environment for mentorship and skill/career growth.&lt;/p&gt;

&lt;h1&gt;
  
  
  Consider Lesser-Known Companies
&lt;/h1&gt;

&lt;p&gt;Do not limit your job search to well-known multinational companies.&lt;/p&gt;

&lt;p&gt;Many lesser-known software companies do great software engineering work and provide fair compensation. Be on the lookout for these hidden gems.&lt;/p&gt;

&lt;h1&gt;
  
  
  Learn Python
&lt;/h1&gt;

&lt;p&gt;Learn Python, particularly for coding interviews.&lt;/p&gt;

&lt;p&gt;Many interviewers understand Python’s relatively simple syntax. With Python, you can get more done in less time and with fewer keystrokes compared to programming languages like Java and C/C++. The time savings add up quickly in a coding interview.&lt;/p&gt;

&lt;p&gt;There are many more useful tips that may improve your job search experience. However, the four tips in this post are some important things to consider as you begin your job search.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Code Review Checklist: 62 Things to Look Out For in Code Reviews</title>
      <dc:creator>David Adamo Jr.</dc:creator>
      <pubDate>Wed, 23 Feb 2022 14:35:27 +0000</pubDate>
      <link>https://dev.to/davidadamojr/code-review-checklist-62-things-to-look-out-for-in-code-reviews-1en8</link>
      <guid>https://dev.to/davidadamojr/code-review-checklist-62-things-to-look-out-for-in-code-reviews-1en8</guid>
      <description>&lt;p&gt;What do you look out for in your code reviews? Is the quality of your code reviews consistent? Do you use a code review checklist?&lt;/p&gt;

&lt;p&gt;There are several reasons why the quality and thoroughness of code reviews may vary significantly across pull requests. Some reasons for inconsistency in code reviews include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The skill and competence level of the code reviewer.&lt;/li&gt;
&lt;li&gt;How much the code reviewer knows about the specific issue(s) addressed in the code change.&lt;/li&gt;
&lt;li&gt;The time of day when the code review was performed.&lt;/li&gt;
&lt;li&gt;The specific programming issues that have been on the reviewer's mind lately.&lt;/li&gt;
&lt;li&gt;The reviewer's perception of the code contributor's competence.&lt;/li&gt;
&lt;li&gt;The programming languages and technologies used in the code change. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A code review checklist is a useful way to improve the quality and consistency of code reviews. Consistent use of checklists decreases the likelihood that a reviewer's focus is skewed toward specific areas of interest or convenience at the expense of other important areas. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.michaelagreiler.com/" title="Dr. Michaela Greiler" rel="noreferrer noopener"&gt;Dr. Michaela Greiler&lt;/a&gt; has done some remarkable work on helping software engineers improve their code reviews. This post presents a checklist, based on Dr. Greiler's work, with 62 things to look out for in code reviews. The questions in this checklist are structured such that each question can be answered with either a YES, NO, or Not Applicable (N/A). In theory, the likelihood that a code change is of acceptable quality is inversely proportional to the number of “NO” answers to the questions in the checklist. Many of the questions in this checklist are subjective and almost completely at the discretion of the code reviewer.&lt;/p&gt;

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

&lt;h3&gt;PR Etiquette&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does this code change address a &lt;a href="https://fagnerbrack.com/one-pull-request-one-concern-e84a27dfe9f1" rel="noreferrer noopener"&gt;single high-level concern&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Are the commit messages &lt;a href="https://blog.oddbit.com/post/2019-06-14-git-etiquette-commit-messages/" rel="noreferrer noopener"&gt;clear and well-written&lt;/a&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Implementation&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does this code change do what it is supposed to do?&lt;/li&gt;
&lt;li&gt;Is there a &lt;a href="https://www.infoq.com/articles/simplicity-manifesto-development/" rel="noreferrer noopener"&gt;simpler&lt;/a&gt; alternative to this code change?&lt;/li&gt;
&lt;li&gt;Are all the new &lt;a href="http://tutorials.jenkov.com/ood/understanding-dependencies.html" rel="noreferrer noopener"&gt;compile-time and run-time dependencies&lt;/a&gt; in this code change necessary and appropriate?&lt;/li&gt;
&lt;li&gt;Does this code change use appropriate frameworks, APIs, libraries, and services instead of custom code whenever possible?&lt;/li&gt;
&lt;li&gt;Is this code change at the right &lt;a href="https://8thlight.com/blog/javier-garc%C3%ADa/2019/06/11/refactoring-levels-of-abstraction.html" rel="noreferrer noopener"&gt;level of abstraction&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Is the code &lt;a href="http://singlepageappbook.com/maintainability1.html" rel="noreferrer noopener"&gt;modular&lt;/a&gt; enough?&lt;/li&gt;
&lt;li&gt;Does this code change use existing code whenever possible instead of introducing new code?&lt;/li&gt;
&lt;li&gt;If this code change does not use similar existing functionality in the codebase, is there a good reason why? &lt;/li&gt;
&lt;li&gt;Does this code change use best practices, &lt;a href="https://refactoring.guru/design-patterns" rel="noreferrer noopener"&gt;design patterns&lt;/a&gt; or language-specific patterns in ways that improve code maintainability, readability, performance, and security?&lt;/li&gt;
&lt;li&gt;Does this code appropriately follow &lt;a href="http://www.cs.utsa.edu/~cs3443/notes/designPrinciples/designPrinciples.html" rel="noreferrer noopener"&gt;Object-Oriented Analysis and Design principles&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Do all classes, methods, and functions have a &lt;a href="https://martinfowler.com/bliki/FunctionLength.html" rel="noreferrer noopener"&gt;reasonable number of lines&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Does this code change add clear value and avoid &lt;a href="https://en.wikipedia.org/wiki/Feature_creep" rel="noreferrer noopener"&gt;feature creep&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Does this code change adhere to the &lt;a href="https://programming-idioms.org/all-idioms" rel="noreferrer noopener"&gt;idioms and code patterns&lt;/a&gt; of the programming language?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Logic Errors and Bugs&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does this code change behave as intended for all use cases you can think of?&lt;/li&gt;
&lt;li&gt;Does this code change properly handle unconventional inputs and external events without breaking?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Error Handling and Logging&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does this code change &lt;a href="https://owasp.org/www-community/Improper_Error_Handling" rel="noreferrer noopener"&gt;handle errors correctly&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Are error messages &lt;a href="https://xd.adobe.com/ideas/process/information-architecture/error-message-design-ux/" rel="noreferrer noopener"&gt;descriptive and user-friendly&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Does this code change produce &lt;a href="https://www.dataset.com/blog/the-10-commandments-of-logging/" rel="noreferrer noopener"&gt;proper logs and debugging information&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Are &lt;a href="https://www.orpiske.net/2011/10/writing-good-log-messages/" rel="noreferrer noopener"&gt;log messages&lt;/a&gt; written in a way that enables easy debugging?&lt;/li&gt;
&lt;li&gt;Does this code change ensure that logs do not &lt;a href="https://cwe.mitre.org/data/definitions/532.html" rel="noreferrer noopener"&gt;expose too much technical information&lt;/a&gt; that could lead to a security issue?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Usability and Accessibility&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Is the proposed solution well designed from a &lt;a href="https://www.nngroup.com/articles/usability-101-introduction-to-usability/" rel="noreferrer noopener"&gt;usability&lt;/a&gt; perspective?&lt;/li&gt;
&lt;li&gt;Does the proposed solution adequately address &lt;a href="https://www.washington.edu/doit/designing-software-accessible-individuals-disabilities" rel="noreferrer noopener"&gt;accessibility concerns&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Are the APIs defined in this code change &lt;a href="https://idratherbewriting.com/learnapidoc/" rel="noreferrer noopener"&gt;well documented&lt;/a&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Ethics and Morality&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Does this code change use data in a way that minimizes or eliminates privacy concerns?&lt;/li&gt;
&lt;li&gt;If this code change adds or alters ways in which people interact with each other, are appropriate measures in place to prevent/limit/report harassment or abuse?&lt;/li&gt;
&lt;li&gt;Does this code change adequately avoid exploitation of behavioral patterns or human weaknesses?&lt;/li&gt;
&lt;li&gt;Does this code change adequately ensure that it does not cause mental or physical harm to users?&lt;/li&gt;
&lt;li&gt;Does this code change adequately ensure that it does not exclude certain groups of people or users?&lt;/li&gt;
&lt;li&gt;Does this code change adequately avoid introducing any algorithm, AI or machine learning &lt;a href="https://en.wikipedia.org/wiki/Algorithmic_bias" rel="noreferrer noopener"&gt;bias&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Does this code change adequately avoid introducing any gender/racial/political/religious/ableist &lt;a href="https://en.wikipedia.org/wiki/Algorithmic_bias" rel="noreferrer noopener"&gt;bias&lt;/a&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Testing and Testability&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Is the code well designed from a &lt;a href="https://www.infoq.com/articles/Testability/" rel="noreferrer noopener"&gt;testability&lt;/a&gt; perspective?&lt;/li&gt;
&lt;li&gt;Does the code change have &lt;a href="https://personal.utdallas.edu/~ewong/SE6367/03-Lecture/15-Test-Adequacy-one-slide.pdf" rel="noreferrer noopener"&gt;enough&lt;/a&gt; automated unit, integration, and system tests? If not, do the existing tests adequately cover the code change?&lt;/li&gt;
&lt;li&gt;Do the test cases in the code change cover all important inputs or edge cases you can think of?&lt;/li&gt;
&lt;li&gt;Are the tests &lt;a href="http://agileinaflash.blogspot.com/2009/02/first.html" rel="noreferrer noopener"&gt;well isolated and independent&lt;/a&gt; from one another?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Dependencies&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Have necessary updates been made to other artifacts related to this code change (e.g. documentation, configuration, README files, etc.)?&lt;/li&gt;
&lt;li&gt;Does this code change adequately consider and address any undesirable effects on other parts of the system?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Security and Data Privacy&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Have all new dependencies been &lt;a href="https://docs.npmjs.com/auditing-package-dependencies-for-security-vulnerabilities" rel="noreferrer noopener"&gt;audited for security vulnerabilities&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Does this code change &lt;a href="https://owasp.org/www-project-mobile-top-10/2014-risks/m5-poor-authorization-and-authentication" rel="noreferrer noopener"&gt;appropriately handle authentication and authorization&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Is sensitive information like user data and credit card information securely handled and stored?&lt;/li&gt;
&lt;li&gt;Does this code change use appropriate encryption schemes when necessary?&lt;/li&gt;
&lt;li&gt;Does this code change properly hide secret information like keys, usernames, and passwords?&lt;/li&gt;
&lt;li&gt;Does this code change properly address security vulnerabilities such as cross-site scripting and SQL injection? Does this code change properly sanitize and validate user input?&lt;/li&gt;
&lt;li&gt;Does this code change properly validate data retrieved from external APIs or libraries?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Performance, Reliability, and Scalability&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Is this code change unlikely to have a significant negative impact on system performance?&lt;/li&gt;
&lt;li&gt;Does this code change include all the useful performance optimizations that you can think of?&lt;/li&gt;
&lt;li&gt;Does this code change have instrumentation for metrics reporting and failure alerts?&lt;/li&gt;
&lt;li&gt;Does this code change use appropriate built-in functions wherever possible?&lt;/li&gt;
&lt;li&gt;Has all debugging code been removed from this code change?&lt;/li&gt;
&lt;li&gt;Are all performance optimizations in this code change necessary?&lt;/li&gt;
&lt;li&gt;Does this code change use some form of &lt;a href="https://en.wikipedia.org/wiki/Cache_(computing)" rel="noreferrer noopener"&gt;caching&lt;/a&gt; whenever appropriate?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Readability&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Is the code easy to understand?&lt;/li&gt;
&lt;li&gt;Are methods and functions &lt;a href="https://martinfowler.com/bliki/FunctionLength.html" rel="noreferrer noopener"&gt;small enough&lt;/a&gt; to be easily readable?&lt;/li&gt;
&lt;li&gt;Are function, method and variable names &lt;a href="https://wiki.c2.com/?MeaningfulName" rel="noreferrer noopener"&gt;meaningful&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Are modules located in appropriate and &lt;a href="https://wiki.c2.com/?MeaningfulName" rel="noreferrer noopener"&gt;meaningfully named&lt;/a&gt; files, folders, and packages?&lt;/li&gt;
&lt;li&gt;Is &lt;a href="https://en.wikipedia.org/wiki/Control_flow" rel="noreferrer noopener"&gt;control flow&lt;/a&gt; in modules, functions, and methods intuitive?&lt;/li&gt;
&lt;li&gt;Is the data flow in modules, functions, and methods intuitive?&lt;/li&gt;
&lt;li&gt;Are all comments in this code change necessary and meaningful?&lt;/li&gt;
&lt;li&gt;Do the comments in this code change describe why and not what?&lt;/li&gt;
&lt;li&gt;Does this project use a linter?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Secondary Review&lt;/h3&gt;

&lt;ul&gt;&lt;li&gt;If this code change impacts different teams, has it been reviewed by people from the affected teams?&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;This code review checklist is also available as a &lt;a href="https://docs.google.com/spreadsheets/d/11Vk6Wi2nOLl5bVlan5w8iGDBwBXekVit5q1yDAD_L7M/edit?usp=sharing" rel="noreferrer noopener" title="spreadsheet"&gt;spreadsheet&lt;/a&gt; to edit and improve as you please. &lt;/p&gt;

</description>
      <category>codereview</category>
      <category>programming</category>
    </item>
    <item>
      <title>17 Things to Know Before Deciding to Get a Ph.D. in Computer Science</title>
      <dc:creator>David Adamo Jr.</dc:creator>
      <pubDate>Mon, 21 Feb 2022 19:11:33 +0000</pubDate>
      <link>https://dev.to/davidadamojr/17-things-to-know-before-deciding-to-get-a-phd-in-computer-science-3mph</link>
      <guid>https://dev.to/davidadamojr/17-things-to-know-before-deciding-to-get-a-phd-in-computer-science-3mph</guid>
      <description>&lt;p&gt;This post is long overdue and marks the start of a series of blog posts about my journey through earning a Ph.D. in Computer Science. &lt;/p&gt;

&lt;p&gt;On August 15, 2012, I moved to the United States of America to accept an offer of admission to a Computer Science Ph.D. program. The decision to pursue a Ph.D. in Computer Science marked the beginning of an arduous five-and-a-half-year journey of self-discovery and personal development. I eventually graduated in December 2017 and it has taken me a few years to settle into life outside of graduate school. &lt;a href="http://davidadamojr.com/research/" title="Peer-Reviewed Publications"&gt;8 peer-reviewed publications&lt;/a&gt;, &lt;a href="https://scholar.google.com/citations?hl=en&amp;amp;user=xA_KeHsAAAAJ" rel="noreferrer noopener" title="https://scholar.google.com/citations?hl=en&amp;amp;user=xA_KeHsAAAAJ"&gt;7 patents&lt;/a&gt;, and &lt;a href="https://www.linkedin.com/in/davidadamojr/" title="https://www.linkedin.com/in/davidadamojr/"&gt;4 full-time software engineering jobs&lt;/a&gt; later, I now have enough mental clarity to reflect on my time in graduate school and share what I wish I knew at the start of the Ph.D. journey. &lt;/p&gt;

&lt;p&gt;Please note that the lessons shared in this post are colored by my particular experience in a Software Engineering-focused research area and at a specific university in the United States. Some of the things mentioned in this post may not apply to all countries, fields of study, and across all universities. Now, without further ado, here are 17 lessons learned in retrospect and things I wish I knew when I started the Ph.D. journey.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/It_takes_a_village" rel="noreferrer noopener" title="https://en.wikipedia.org/wiki/It_takes_a_village"&gt;It takes a village&lt;/a&gt; to earn a Ph.D.&lt;/li&gt;
&lt;li&gt;Choose your advisor(s) wisely and carefully.&lt;/li&gt;
&lt;li&gt;Be mindful of academic politics.&lt;/li&gt;
&lt;li&gt;Avoid resource-intensive research areas.&lt;/li&gt;
&lt;li&gt;Software development skill matters much less than you think.&lt;/li&gt;
&lt;li&gt;Experiment design skill is more valuable than you think.&lt;/li&gt;
&lt;li&gt;Write often and publish early.&lt;/li&gt;
&lt;li&gt;You don't write as well as you think.&lt;/li&gt;
&lt;li&gt;Grades matter less than you think.&lt;/li&gt;
&lt;li&gt;Stay funded.&lt;/li&gt;
&lt;li&gt;There is an alarming disconnect between academia and industry practice.&lt;/li&gt;
&lt;li&gt;Teaching is difficult but sometimes rewarding.&lt;/li&gt;
&lt;li&gt;The non-research career opportunity cost is real and often incredibly high.&lt;/li&gt;
&lt;li&gt;Squash impostor syndrome often and early.&lt;/li&gt;
&lt;li&gt;Professors are human too.&lt;/li&gt;
&lt;li&gt;There are potential immigration advantages.&lt;/li&gt;
&lt;li&gt;Do not get a Ph.D. 😊&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In subsequent posts, I will elaborate on each of these lessons. Each person's experience in a Computer Science Ph.D. program is unique, and one person's experience is not necessarily a reliable predictor of another's. Having said that, I hope that my experience and perspective on these topics will help people who may be considering a foray into the &lt;a href="https://www.scholat.com/teamwork/teamworkdownloadscholar.html?id=4924&amp;amp;teamId=1158" rel="noreferrer noopener" title="https://www.scholat.com/teamwork/teamworkdownloadscholar.html?id=4924&amp;amp;teamId=1158"&gt;Ph.D. grind&lt;/a&gt;(pdf book).&lt;/p&gt;

</description>
      <category>education</category>
      <category>computerscience</category>
      <category>career</category>
    </item>
    <item>
      <title>Managing Simultaneous Learning and Productivity in Software Development</title>
      <dc:creator>David Adamo Jr.</dc:creator>
      <pubDate>Mon, 21 Feb 2022 18:55:55 +0000</pubDate>
      <link>https://dev.to/davidadamojr/managing-simultaneous-learning-and-productivity-in-software-development-3abp</link>
      <guid>https://dev.to/davidadamojr/managing-simultaneous-learning-and-productivity-in-software-development-3abp</guid>
      <description>&lt;p&gt;The abundance of opportunities to learn new things is one of my favorite aspects of being a Software Developer. However, software development in professional settings is often severely time-constrained, so I rarely find enough time to gain an expert-level understanding of the numerous concepts I encounter during the course of my work. These time constraints typically affect how deeply I am able to absorb new technical concepts and still maintain high levels of productivity. Whenever I am faced with a situation that calls for balancing time, learning, and action, my inclination is to formulate and apply some sort of structure to the situation. This post describes the framework I use to manage the simultaneous productivity and meaningful learning in time-constrained contexts.&lt;/p&gt;

&lt;p&gt;I like to think about the learning process as a series of questions and knowledge levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level 0: What is it called?&lt;/li&gt;
&lt;li&gt;Level 1: What does it do?&lt;/li&gt;
&lt;li&gt;Level 2: What are some alternatives and why does this one exist?&lt;/li&gt;
&lt;li&gt;Level 3: How does it work/How does it do what it does?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I often use this framework to calibrate how deeply I need to understand new technical concepts within the context of a specific task and associated time constraints. I consider &lt;strong&gt;levels 0 and 1&lt;/strong&gt; to be “shallow” understanding. &lt;strong&gt;Level 2&lt;/strong&gt; is neither shallow nor deep, but often sufficient to satisfy my curiosity and help me make more informed choices. &lt;strong&gt;Level 3 &lt;/strong&gt;represents deep understanding. This learning framework may be generalizable to other subject areas and professions, although I use it most often within the context of software development.&lt;/p&gt;

&lt;p&gt;Now let us work through a scenario where this framework may be useful. Consider the function below (written in Python): &lt;/p&gt;

&lt;pre&gt;
def first_n_numbers(n):
    num = 0
    while num &amp;lt; n:
        yield num
        num += 1
&lt;/pre&gt;

&lt;p&gt;The first time I saw a Python function like the one above, the &lt;em&gt;yield&lt;/em&gt; statement seemed rather strange to me. What thought process did I follow to learn more about this strange &lt;em&gt;yield &lt;/em&gt;statement? You guessed it!&lt;em&gt; &lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Level 0: What is it called?&lt;/h2&gt;

&lt;p&gt;This level of understanding focuses on concepts and terminology. I consider this to be the most fundamental level of understanding one can achieve about a given subject. Knowing the proper terminology that applies to a particular subject of interest is an invaluable foundation for seeking further information.&lt;/p&gt;

&lt;p&gt;In the context of our example with the Python function and &lt;em&gt;yield&lt;/em&gt; statement, a quick google search for the phrase “python yield statement” tells me that this construct is called a “generator function”, and is related to iterables, iterators, and loops in Python. If I am really in a hurry and the nature of my task allows, I may keep all these related terms in mind for later, stop at this level of inquiry, and move on with the task. More often than not, I will proceed to level 1 to gain a better understanding of what these “generator functions” do.&lt;/p&gt;

&lt;p&gt;In some scenarios, one may already know the right terminology for the subject of interest. For example, if I were reading an article or a book on functional programming and came across the word &lt;em&gt;combinator&lt;/em&gt;, it would be rather obvious what exact term I need to search for to acquire additional information. In such a scenario where the precise name of a concept is obvious, I’ll immediately begin further learning at level 1.&lt;/p&gt;

&lt;h2&gt;Level 1: What does it do?&lt;/h2&gt;

&lt;p&gt;This level focuses on understanding the immediate effect(s) of using or adopting a particular tool, concept, or programming construct. I typically stop at this level when my top priority is to complete a task, rather than to gain a deep understanding of the particular subject of interest.&lt;/p&gt;

&lt;p&gt;In our generator function example, this level of understanding focuses on figuring out what generator functions do when you use them. A little digging on the interwebs tells me that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A generator function i.e. a function with a yield statement, acts like an &lt;a href="https://www.w3schools.com/python/python_iterators.asp"&gt;iterator&lt;/a&gt;. Therefore, such a function can be used as part of a &lt;em&gt;&lt;code&gt;for&lt;/code&gt; &lt;/em&gt;loop as in &lt;em&gt;&lt;code&gt;for i in first_n_numbers(10)&lt;/code&gt;&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;The &lt;em&gt;yield &lt;/em&gt;statement in a function provides a result to the caller without destroying local variables.&lt;/li&gt;
&lt;li&gt;Each call to a generator function resumes execution from where it left off after the most recent call.&lt;/li&gt;
&lt;li&gt;Generators produce iterables, but they are not collections and thus have no length.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For programming constructs, it is often helpful to find a few code examples at this level to help illustrate proper syntax and semantics.&lt;/p&gt;

&lt;h2&gt;Level 2: What are some alternatives and why does this one exist?&lt;/h2&gt;

&lt;p&gt;This is where learning starts to go beneath the surface. This level focuses on identifying alternative ways to achieve the same or similar objectives, and understanding how the subject of interest compares to the identified alternatives. Knowledge acquired at this level helps me to make informed decisions regarding when to apply the subject of interest or choose some other alternative that might be less elegant but more widely understood.&lt;/p&gt;

&lt;p&gt;So what are some alternatives to using generator functions as defined in our example? At this level, I will discover that instead of using a generator function with a yield statement, we could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://wiki.python.org/moin/Generators"&gt;Write a function that constructs and returns a list in memory&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create a class with the &lt;a href="https://wiki.python.org/moin/Generators"&gt;generator pattern&lt;/a&gt; and use an instance of the class as an iterator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So why would one choose to use a generator function instead of one of the other alternatives outlined above? If the objective is to produce something that can be iterated over, why not just construct a regular Python list, return the newly constructed list and be done with it? It is at this level that I will discover that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing a function that constructs the full list in memory does not scale well. If each item in the list happens to take up a lot of space, or we need to generate a stupendously large number of items, we could run out of memory real quick.&lt;/li&gt;
&lt;li&gt;Creating a class with the generator pattern helps us deal with the performance issue, but it involves quite a bit of boilerplate code and convoluted logic relative to using a generator function. The boilerplate becomes more of an annoyance if we have to create many such classes with the generator pattern.&lt;/li&gt;
&lt;li&gt;Generator functions are a convenient shortcut to building iterators that are memory-efficient with clear natural logic and without annoying boilerplate code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this level of knowledge, I am able to understand when it is beneficial to use a generator function with a &lt;em&gt;yield&lt;/em&gt; statement and when it is not. I might choose to use a simple list or some other simple iterable, rather than blindly use a generator. A simple iterable in memory would be a reasonable choice in scenarios where I have a small constrained list of items and do not need to worry about memory and performance. &lt;/p&gt;

&lt;p&gt;Ultimately, I have found the knowledge gained at this level to be incredibly valuable for communicating with others and explaining the rationale behind my decisions. Communication and informed decision making is a key ingredient in successful engineering teams. This level of understanding could help foster useful conversations, particularly in code reviews.&lt;/p&gt;

&lt;h2&gt;Level 3: How does it work/How does it do what it does?&lt;/h2&gt;

&lt;p&gt;I consider this to be the deepest level of understanding in my framework, assuming the other levels have been sufficiently explored. I typically resort to this level when my primary goal is to teach a class or write technical documentation about a given topic. Most of the time, I do not reach this level of understanding, as the time and effort required often outweigh the immediate benefits. This level is potentially infinite and requires an understanding of how things work at a level beyond what most situations require. For technical concepts in software engineering, many universities spend a significant amount of time teaching concepts at this level and things can get quite arcane pretty fast.&lt;/p&gt;

&lt;p&gt;For generator functions, it is at this level that I will seek to understand all of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python interpreter internals&lt;/li&gt;
&lt;li&gt;Python bytecode&lt;/li&gt;
&lt;li&gt;Stack frames&lt;/li&gt;
&lt;li&gt;Heap memory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have not yet taken the time to fully understand &lt;em&gt;generators&lt;/em&gt; at this level as I imagine it is going to require quite a bit of time and dedication to learn all the other associated concepts that make generators work the way they do. For anyone interested in understanding generators at this level, the “How Python Generators Work” section of this &lt;a href="http://aosabook.org/en/index.html"&gt;AOSA&lt;/a&gt; &lt;a href="http://aosabook.org/en/500L/a-web-crawler-with-asyncio-coroutines.html"&gt;book chapter&lt;/a&gt; might help. Good luck, and have some Ibuprofen or Tylenol close by just in case you get a headache. :)&lt;/p&gt;

&lt;p&gt;In this post, I have outlined the framework I use when I need to balance the tradeoff between learning new technical concepts and rapid progress toward the completion of a software development task. I use this framework to calibrate how deeply I need to understand new technical concepts in time-constrained situations that require simultaneous productivity and learning. This is a daily reality for me as a professional Software Developer. I hope others find it useful, enlightening, or at least amusing.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>python</category>
      <category>productivity</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
