<?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: Bruno says ✍️</title>
    <description>The latest articles on DEV Community by Bruno says ✍️ (@brunoraljic).</description>
    <link>https://dev.to/brunoraljic</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%2F449366%2F7349cbcf-0923-414d-9355-1bb7a60e1c70.png</url>
      <title>DEV Community: Bruno says ✍️</title>
      <link>https://dev.to/brunoraljic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brunoraljic"/>
    <language>en</language>
    <item>
      <title>Getting started with SonarQube (java, maven and docker)</title>
      <dc:creator>Bruno says ✍️</dc:creator>
      <pubDate>Tue, 17 Nov 2020 14:47:14 +0000</pubDate>
      <link>https://dev.to/brunoraljic/getting-started-with-sonarqube-java-maven-and-docker-244n</link>
      <guid>https://dev.to/brunoraljic/getting-started-with-sonarqube-java-maven-and-docker-244n</guid>
      <description>&lt;p&gt;How do we know if the code we write is good enough? Error free? Not vulnerable? Not smelly?&lt;/p&gt;

&lt;p&gt;There are some tools that can show you that, and today I'm writing about &lt;a href="https://www.sonarqube.org/"&gt;SonarQube&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;But, since I like the approach with minimum steps required, I'll write just as much as I think it's necessary for the beginning. &lt;/p&gt;

&lt;p&gt;I'll even set it up with Docker image. In case you're not familiar with it, you may want to check &lt;a href="https://brunosays.com/docker-images-intro-for-beginners"&gt;Docker Images - Intro for beginners&lt;/a&gt; that I wrote. &lt;/p&gt;

&lt;h2&gt;
  
  
  SonarQube as a Docker image
&lt;/h2&gt;

&lt;p&gt;Let's keep it simple, we'll run a SonarQube container and after we are done playing with that, we can wipe it off from our system like it never existed. No external installations or things like that&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull sonarqube:8.5.1-community
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where did I get this? There's a docker pull command on the &lt;a href="https://www.sonarqube.org/downloads/"&gt;SonarQube download&lt;/a&gt; page, ready to be copied. Check it out, newer versions may be available.&lt;/p&gt;

&lt;p&gt;OK, image is there, now what? Like with every docker image, check the documentation on Docker Hub, &lt;a href="https://hub.docker.com/_/sonarqube"&gt;here&lt;/a&gt; in our case.&lt;/p&gt;

&lt;p&gt;You might want to read everything there but I already did that for you. There will be a link that points to this piece of documentation&lt;/p&gt;

&lt;p&gt;Step 1. Find the Community Edition Docker image on Docker Hub &lt;em&gt;(we did this already)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Step 2. Start the server 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;$ docker run -d --name sonarqube -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true -p 9000:9000 sonarqube:8.5.1-community
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now I don't know what this &lt;code&gt;SONAR_ES_BOOTSTRAP_CHECKS_DISABLE&lt;/code&gt; flag is, but it's not important to understand for now. Obviously you have to put it, since it's in bare minimum quick start documentation. And, you always can use a Google to check it on your own. I did a brief check and saw that SonarQube use ElasticSearch underneath and this flag prevents some checks that we don't care about at the moment. We wan't to see SonarQube up and running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up SonarQube project
&lt;/h2&gt;

&lt;p&gt;Log in to &lt;a href="http://localhost:9000"&gt;http://localhost:9000&lt;/a&gt; with System Administrator credentials (login=admin, password=admin). If you can't open the page immediately, wait a bit, don't panic. If you keep refreshing like I did, you'll see this at some point&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RoYYodNT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604401149579/v1bLHQ3v6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RoYYodNT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604401149579/v1bLHQ3v6.png" alt="Screenshot 2020-11-03 at 11.56.52.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While logging in, you may notice this warning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Embedded database should be used for evaluation purposes only&lt;/p&gt;

&lt;p&gt;The embedded database will not scale, it will not support upgrading to newer versions of SonarQube, and there is no support for migrating your data out of it into a different database engine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's totally fine for now. We could set up external DB or map the storage volume, but for the purpose of quick start we'll stick with the embedded DB. Definitely not recommended for production projects.&lt;/p&gt;

&lt;p&gt;Click on that &lt;code&gt;Create new project&lt;/code&gt; and put some names there&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wLSbub9v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604401489148/csi7QIvp6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wLSbub9v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604401489148/csi7QIvp6.png" alt="Screenshot 2020-11-03 at 12.04.36.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next step is to generate a project token, which will be used for identification. Bear in mind that SonarQube will have access to your code (and have a copy for analysis purposes), so it's important that you protect it. Again, important in production. This is a quick showcase, so you don't have to worry too much about keeping those tokens, let's just make it work. &lt;/p&gt;

&lt;p&gt;Continue setting up the project, select &lt;code&gt;Java&lt;/code&gt; and then select &lt;code&gt;Maven&lt;/code&gt; as a build tool. This will generate for you the command that you need to execute in your project directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn sonar:sonar \
  -Dsonar.projectKey=hashnode-blog-showcase \
  -Dsonar.host.url=http://localhost:9000 \
  -Dsonar.login=YOUR-TOKEN-HERE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for the &lt;code&gt;BUILD SUCCESS&lt;/code&gt; message from Maven and go to &lt;a href="http://localhost:9000"&gt;http://localhost:9000&lt;/a&gt; again. Even better, you can click on the link in the maven log.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ANALYSIS SUCCESSFUL, you can browse http://localhost:9000/dashboard?id=hashnode-blog-showcase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Project overview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I5qCsAEJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604402295836/cn4HKYosYM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I5qCsAEJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604402295836/cn4HKYosYM.png" alt="Screenshot 2020-11-03 at 12.16.16.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see something like this. So let's just take a brief overview what you can see here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quality gate status&lt;/strong&gt;: Passed. You can set certain rules for quality gate and based on them you'll get a boolean, passed or not. Rule can be for example &lt;em&gt;Test coverage 80%&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New Code / Overall Code&lt;/strong&gt;: In the Overall, you can get all the reports within the project code base. In New Code you can see the diff after running a second analysis of the same branch. So you can see only the analysis of your latest changes. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Main reporting&lt;/strong&gt;: Bugs, Vulnerabilities, Security issues, Code smells and technical debts. All with links included so you can dive in. Technical debt is measured by some average assumptions made by SonarQube and it can give you the feeling how much time will you spent on solving these things.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage&lt;/strong&gt;: I do have 3 unit tests, and SonarQube detects them, which is nice. However, I remember there has to be some SonarQube plugins activated (or configured) so it can detect line coverage. As you can see it's 0.0% at the moment, which I know it's not correct. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplication&lt;/strong&gt;: This section can find and show how much duplicated code do you have in terms of line and percentage of your total code base.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Diving in, how can SonarQube help us?
&lt;/h2&gt;

&lt;p&gt;OK, we see that there is one bug and 11 code smells on this project. How can we proceed? Well, the general rule of thumb is to start with Bugs, Vulnerabilities and Security issues. &lt;/p&gt;

&lt;p&gt;What I like about SonarQube is that they report on &lt;strong&gt;what&lt;/strong&gt;, &lt;strong&gt;where&lt;/strong&gt; and &lt;strong&gt;how&lt;/strong&gt; parts. Let's chase that bug. If I click on the link in the Bugs part, it will show me the details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w3gofbNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406205567/sq5VB-E5O.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w3gofbNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406205567/sq5VB-E5O.png" alt="Screenshot 2020-11-03 at 13.21.08.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can even navigate to the code and it will show me exactly where it is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WMhgdOvq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406250745/3l6TZWxnv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WMhgdOvq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406250745/3l6TZWxnv.png" alt="Screenshot 2020-11-03 at 13.21.35.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I also like, is that SonarQube is giving you Severity overview, and you can see it's &lt;code&gt;Major&lt;/code&gt; severity. There are two levels above &lt;code&gt;Critical&lt;/code&gt; and &lt;code&gt;Blocker&lt;/code&gt;. Pay attention to these.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OeKKoac1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406361053/yS7MektOA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OeKKoac1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406361053/yS7MektOA.png" alt="Screenshot 2020-11-03 at 13.24.44.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next cool thing I like about it is that you have all the description why you should change something. You probably saw that &lt;code&gt;Why is this an issue?&lt;/code&gt; link. &lt;strong&gt;You'll often learn a thing or two from there&lt;/strong&gt;. They also provide both compliant and non-compliant solutions. I'll show it in the next screenshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8UmeqL6I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406618746/-cuu0-7BG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8UmeqL6I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406618746/-cuu0-7BG.png" alt="Screenshot 2020-11-03 at 13.29.49.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See? A very detailed overview. And you know what to do after reading it. Let's check the other issues we have so you can have a better picture how it looks like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TnuKq4Lu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406857882/JgYstBZmM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TnuKq4Lu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1604406857882/JgYstBZmM.png" alt="Screenshot 2020-11-03 at 13.32.06.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your mileage may vary. If you have bigger project, you'll have more diverse issues. But, you get a nice foundation to continue from here.&lt;/p&gt;

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

&lt;p&gt;SonarQube is static code analysis tool. It will check your code against certain rules to see if there are some bugs, security issues, pitfalls etc. &lt;/p&gt;

&lt;p&gt;You should use it since it gives you a lot of explanation why and how you can improve your code. Of course, you don't have to obey 100%, but at least consider making changes to your code.&lt;/p&gt;

&lt;p&gt;You can set it up really simple with Maven, and especially if you install it as a Docker image. &lt;/p&gt;

&lt;p&gt;The scope for this blog post is to show you the basics of SonarQube analysis. I plan to write a bit more on this topic later. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/brunoraljic"&gt;@brunoraljic&lt;/a&gt;&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>maven</category>
      <category>docker</category>
      <category>java</category>
    </item>
    <item>
      <title>Why I (don’t) use TDD</title>
      <dc:creator>Bruno says ✍️</dc:creator>
      <pubDate>Sun, 16 Aug 2020 16:16:23 +0000</pubDate>
      <link>https://dev.to/brunoraljic/why-i-don-t-use-tdd-6oj</link>
      <guid>https://dev.to/brunoraljic/why-i-don-t-use-tdd-6oj</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello everyone. I want to bring back one of my old articles. Wrote it in 2012. Long time ago. I found it while searching something on web archive site. &lt;br&gt;
I'll copy the content as it is, my thoughts on this topic haven't changed so much. This republishing is me paying tribute to that article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Test driven development is a very powerful thing. Although I don’t use it on every day basis, I’m a big admirer of the whole TDD concept. When I first heard of it, it made me laugh. It sounded impossible to me (especially for my poor skills). It was something like looking into the future. How the hell I can possibly know what and how will I implement something. Sounds familiar?&lt;/p&gt;

&lt;p&gt;From my point of view, it’s not easy at all to cross the border and step into the TDD world. You have to think differently. And you probably won’t change your mind over night. Or maybe you will, like in my case when the TDD was the only way out of the problem.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why I don’t use it?
&lt;/h2&gt;

&lt;p&gt;Well, let me present you one more scenario you are, I’m sure, familiar with. New requirements are there and, of course, deadline is near. If you step back and take a look at the whole picture, you’ll see that TDD can save you in general a lot of time. But when the deadline is near we are looking only the small piece of that picture. We just want to finish something before our next deployment, write some test after the implementation and forget about it (until our next meeting with Mr Debugger).&lt;/p&gt;

&lt;p&gt;Another thing, I still think you need to be very experienced developer in order to perform truly test driven development all the time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why I do use it?
&lt;/h2&gt;

&lt;p&gt;As I wrote before, I didn’t “believe” in TDD until it provided me an exit from a very tricky situation with lots of conditions, loops and complicated logic. I started to write code in a usual way, finished few blocks of code, but soon it became so big I didn’t know where to change, what to change, and if I change something will it work as before. My brain was just over capacity. A colleague of mine told me I was ready for one “TDD session”. He started with really simple tests and forced me to write the rest. Of course, he helped me to finish it later, also with some refactoring. That was the point where I started to look differently at TDD.&lt;/p&gt;

&lt;p&gt;I don’t always TDD… But when I do it, it’s because I’m working on something very very complicated, or it’s something I wan’t to be 300% sure it’s working as I want (some financial stuff for example). It doesn’t need to be complicated or serious all the time. I tend to do TDD when I feel I could easily make mistakes and spend more time in debug mode than in developing. Those are situations when I use TDD.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are not allowed to write any production code unless it is to make a failing unit test pass.&lt;/p&gt;

&lt;p&gt;-- &lt;cite&gt;Robert C. Martin (Uncle Bob)&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Short example
&lt;/h2&gt;

&lt;p&gt;I hope this simple Java example will be enough to present you a basics of TDD. Imagine you have a simple ajax call and as a result you want your Java object presented as JSON. Ok, I know, you already have many ways to convert the Java object to JSON, but for this purpose lets convert it manually. As you can see in example below, there are a lot of double quotes. In Java, you have to escape them if you want to have them in your string, so there is a possibility that you will forget to escape all the double quotes. That’s one of the reasons I found this example interesting for TDD.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// JSON example
{"menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
  }
}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, let’s say you have list of &lt;code&gt;User&lt;/code&gt; objects, and you want to create JSON from it, but you don’t want to include all user fields, just few of them, for example first and last name.&lt;/p&gt;

&lt;p&gt;We will start from the beginning. First we will write a test for a case when the list of users is &lt;code&gt;null&lt;/code&gt;. For this case we will throw a &lt;code&gt;IllegalArgumentException&lt;/code&gt;. I will use this example to show you how to properly test an exceptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test(expected = IllegalArgumentException.class)
public void testExtractUserNullAsList() {
    // preparing test data
    List&amp;lt;User&amp;gt; users = null;

    try {
        // testing the method
        ModelMapper.extractUsers(users);
    } catch (IllegalArgumentException e) {
        assertEquals("user list is null", e.getMessage());
        throw e;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After that, you’ll write an implementation to make your test pass. Notice the line138, which is telling that it is OK for this test to throw the exception. Another thing, I put the method into the try-catch block. You can make this test pass without putting the method into the try-catch block. The thing is, when you have more complicated tests where you expect some method calls, only way to verify all of them is to verify them in the catch block and then re-throw the exception. So, if you omit the try-catch block, your test will pass (as you expect the exception) but many of your mocks won’t be verified. Below is simple implementation that will make the first test pass.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static String extractUsers(List&amp;lt;User&amp;gt; users) {
   if (users == null) {
       throw new IllegalArgumentException("user list is null");
   }

   return null;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, let’s make another test. This time, we will pass the empty list. We are taking care of the small things first. Later we will do the complicated things. That’s how you should write your tests. For now, we want the empty JSON object to be returned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void testExtractUsersEmptyList() {
    // preparing test data
    List&amp;lt;User&amp;gt; users = new ArrayList&amp;lt;User&amp;gt;();

    // testing the method
    String result = ModelMapper.extractUsers(users);

    // assertions
    assertEquals("{}", result);

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After adding some code, our method now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static String extractUsers(List&amp;lt;User&amp;gt; users) {
    if (users == null) {
        throw new IllegalArgumentException("user list is null");
    }

    if (users.isEmpty()) {
        return "{}";
    }

    return null;
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The next thing, we want to write tests for case we have few users in that list. First, we will write a test, of course, where we will define what we want as a result of the method. That test will look something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
 public void testExtractUsers() {
    // preparing test data
    User john = createDummyUser(1, "John", "Doe");
    User jane = createDummyUser(2, "Jane", "Doe");
    List&amp;lt;User&amp;gt; users = new ArrayList&amp;lt;User&amp;gt;();
    users.add(john);
    users.add(jane);

    // method to test
    String result = ModelMapper.extractUsers(users);

    // assertions
    assertEquals("{\"users\":[{\"id\":\"1\",\"name\":\"John Doe\"},{\"id\":\"2\",\"name\":\"Jane Doe\"}]}", result);

 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Of course, if we run this test now, it will fail. Now, we’ll extend our implementation. After finishing the implementation and successfully escaping all of the double quotes, my method now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static String extractUsers(List&amp;lt;User&amp;gt; users) {
    if (users == null) {
        throw new IllegalArgumentException("user list is null");
    }

    if (users.isEmpty()) {
        return "{}";
    } else {
        StringBuilder sb = new StringBuilder();
        sb.append("{\"users\":[");
        for (User u : users) {
            sb.append("{\"id\":\"")
            .append(u.getId())
            .append("\",")
            .append("\"name\":\"")
            .append(u.getFirstName())
            .append(" ")
            .append(u.getLastName())
            .append("\"}");
    }

    sb.append("]}");

    return sb.toString();

    }
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But, after running test, I realize I missed something. Test failed because I didn’t separate users by comma. This is where tests are also helpful. If I didn’t covered this with tests, I could continue to develop without noticing that I’m missing this comma and (maybe) I could have long debug time in Javascript in order to find why I can’t parse the response properly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m_sTSwY3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1597593139559/fRJ9Fiphv.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m_sTSwY3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1597593139559/fRJ9Fiphv.jpeg" alt="tdd.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s my method after small modifications:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static String extractUsers(List&amp;lt;User&amp;gt; users) {
    if (users == null) {
        throw new IllegalArgumentException("user list is null");
    }

    if (users.isEmpty()) {
        return "{}";
    } else {
        StringBuilder sb = new StringBuilder();
        sb.append("{\"users\":[");
        for (User u : users) {
        sb.append("{\"id\":\"")
        .append(u.getId())
        .append("\",")
        .append("\"name\":\"")
        .append(u.getFirstName())
        .append(" ")
        .append(u.getLastName())
        .append("\"}");

        if (users.indexOf(u) &amp;lt; users.size() - 1) {
            sb.append(",");
        }
    }
    sb.append("]}");

    return sb.toString();

    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;OK, now I can continue. But, let’s say I don’t like that &lt;code&gt;indexOf(u)&lt;/code&gt; mumbo jumbo magic. It doesn’t look nice. I have an idea and with all these tests, it won’t be a problem to do the refactoring. After all, refactoring is one of the steps in the TDD.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fail, pass, refactor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One question for you. Imagine you have some complicated Javascript component that do a lot of work and hardly relies on your JSON response and you don’t have unit tests. Would you dare to do the refactoring if you have a deadline? Would you dare to do the refactoring at all? In this case, we have encountered with the double quotes escaping and adding commas. If we had few more things like that, every one of them will be a valid argument against the refactoring.&lt;/p&gt;

&lt;p&gt;Let’s get back to the refactoring. In this example I’ll use &lt;code&gt;Iterator&lt;/code&gt; because the &lt;code&gt;hasNext()&lt;/code&gt; method will be perfect replacement in the &lt;code&gt;if&lt;/code&gt; statement. Next step is to refactor until the tests are green again. After introducing &lt;code&gt;Iterator&lt;/code&gt;, my method looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static String extractUsers(List users) {
    if (users == null) {
        throw new IllegalArgumentException("user list is null");
    }

    if (users.isEmpty()) {
        return "{}";
    } else {
        StringBuilder sb = new StringBuilder();

        sb.append("{\"users\":[");

        Iterator&amp;lt;User&amp;gt; userIterator = users.iterator();

        while (userIterator.hasNext()) {
            User u = userIterator.next();
            sb.append("{\"id\":\"")
            .append(u.getId())
            .append("\",")
            .append("\"name\":\"")
            .append(u.getFirstName())
            .append(" ")
            .append(u.getLastName())
            .append("\"}");

            if (userIterator.hasNext()) {
                sb.append(",");
            }
        }

        sb.append("]}");

        return sb.toString();

    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Epilogue
&lt;/h2&gt;

&lt;p&gt;In this blog post I didn’t say anything new regarding the TDD concept. There are already a million blogs about it. It’s more like to say what I think about the TDD.&lt;/p&gt;

&lt;p&gt;Example in the end was chosen because it’s not complicated to present it, and still can be used to explain few TDD things. We gone through writing test from very simple implementation to the final, let’s say, complicated implementation. We also see how can it help you to see where did you go wrong, and at the end we gone through the refactoring. It’s amazing when a programmer knows the application will work the same way after the refactoring, and the well written test will say – &lt;strong&gt;“Yes, you did the refactoring right”.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the end, we all know TDD is good but still we don’t use it. From my point of view, it can be explained as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Life is too short to remove USB safely!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Thanks for reading. As I wrote in the beginning this is the article from 2012. That means the code examples, skills and everything is also from 2012. The only thing I've changed is the referencing exact lines in the code examples. In the previous blog I had a highlighter that included those numbers and this one is without it.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>testing</category>
      <category>mindset</category>
    </item>
    <item>
      <title>Search GitHub instead of Stackoverflow when in trouble</title>
      <dc:creator>Bruno says ✍️</dc:creator>
      <pubDate>Mon, 10 Aug 2020 13:25:09 +0000</pubDate>
      <link>https://dev.to/brunoraljic/search-github-instead-of-stackoverflow-when-in-trouble-1893</link>
      <guid>https://dev.to/brunoraljic/search-github-instead-of-stackoverflow-when-in-trouble-1893</guid>
      <description>&lt;p&gt;Usually when we wan’t to try new things (new libraries, new framework, new language), we’re not quite sure how the code would look like in the end, or what is necessary to configure it correctly.&lt;/p&gt;

&lt;p&gt;We follow the documentation, but suddenly there’s one step missing and you’re stuck. Or the documentation authors assume you know enough, but you’re sitting there, feeling dumb and then it comes to you:&lt;/p&gt;

&lt;p&gt;I SHOULD GOOGLE IT!&lt;/p&gt;

&lt;p&gt;Hoping for that first result, including Stackoverflow question. But then comes describing your own problems. So you try one thing, and the results are promising but 0 value. You return and modify search query, but the same outcome. So you know the answer is so close, but you just can’t formulate your query to map it 1:1 to your problem. And you feel even more dumb, because you can’t solve a problem of unique username in a new framework, although YOU KNOW HOW TO GOOGLE IT, but it still don’t give you desired results.&lt;/p&gt;

&lt;p&gt;So, instead of trying descriptive approach, where the result depends on how well can you describe your problem or express yourself, why not try direct approach. Copy one line of code that you think other should’ve written in their projects before and search for them in GitHub. Now the result depends more on what you’ve copied, not how did you express yourself. And it’s less likely to be “misunderstood”.&lt;/p&gt;

&lt;p&gt;You’ll bee amazed about the results. You’re probably not the first person implementing something, and you’ll often find hundreds of thousands repos where others had implemented the same thing. And it’s probably working code, since people USUALLY keep their repos working.&lt;/p&gt;

&lt;p&gt;Often, you’ll find another approaches. Some of them are not expected at all. Maybe you have one idea in mind, bot someone solved the same thing in totally different way. Maybe one line in some side configuration that you weren’t aware of at all.&lt;/p&gt;

&lt;p&gt;So, be quick in finding your answers, be productive!&lt;br&gt;
—&lt;br&gt;
Follow me on &lt;a href="https://twitter.com/brunoraljic"&gt;@brunoraljic&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mindset</category>
      <category>productivity</category>
      <category>github</category>
    </item>
  </channel>
</rss>
