<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Better Code</title>
    <description>Better Code AB is an IT consulting company owned and operated by  Max Wenzin in Stockholm, Sweden.
</description>
    <link>https://www.bettercode.se/</link>
    <atom:link href="https://www.bettercode.se/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 15 Jan 2023 19:48:34 +0000</pubDate>
    <lastBuildDate>Sun, 15 Jan 2023 19:48:34 +0000</lastBuildDate>
    <generator>Jekyll v3.9.2</generator>
    
      <item>
        <title>Migrated web site from Wordpress to Jekyll</title>
        <description>&lt;p&gt;This site as now been migrated from Wordpress to Jekyll. The simplicity and speed of a static web site suits my needs much better that Wordpress.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;Some of the old blog posts have been pruned.&lt;/p&gt;

&lt;p&gt;Please note that I rarely write blog posts, but when I do I mostly do it on: &lt;a href=&quot;http://blog.crisp.se/author/maxwenzin&quot;&gt;http://blog.crisp.se/author/maxwenzin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href=&quot;http://jekyllrb.com/docs/home&quot;&gt;Jekyll docs&lt;/a&gt; for more info on how to get the most out of Jekyll. File all bugs/feature requests at &lt;a href=&quot;https://github.com/jekyll/jekyll&quot;&gt;Jekyll’s GitHub repo&lt;/a&gt;. If you have questions, you can ask them on &lt;a href=&quot;https://talk.jekyllrb.com/&quot;&gt;Jekyll Talk&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Sun, 13 Mar 2016 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2016/03/13/migrated-from-wordpress-to-jekyll.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2016/03/13/migrated-from-wordpress-to-jekyll.html</guid>
        
        <category>jekyll</category>
        
        
      </item>
    
      <item>
        <title>Blogging on the Crisp blog</title>
        <description>&lt;!--more--&gt;

&lt;p&gt;At the moment I do most of my blogging (if at all) at &lt;a href=&quot;http://blog.crisp.se/author/maxwenzin&quot;&gt;http://blog.crisp.se/author/maxwenzin&lt;/a&gt; so you’re welcome to go there and read about &lt;a href=&quot;http://blog.crisp.se/2012/10/22/maxwenzin/five-team-principles&quot;&gt;Five fundamental principles for building software development teams&lt;/a&gt; or other posts by me or my Crisp collegues.&lt;/p&gt;
</description>
        <pubDate>Tue, 16 Apr 2013 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2013/04/16/blogging-on-the-crisp-blog.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2013/04/16/blogging-on-the-crisp-blog.html</guid>
        
        <category>dev</category>
        
        <category>crisp</category>
        
        <category>agile</category>
        
        
      </item>
    
      <item>
        <title>Challenges of a distributed Scrum Team</title>
        <description>&lt;!--more--&gt;

&lt;p&gt;The Mobile Team at Projectplace has people both in Stockholm, Sweden and in Bangalore, India. This gives them a set of challenges that they need to overcome. I current work as a Scrum Master for them at Projectplace and I’ve written &lt;a href=&quot;http://blog.crisp.se/2012/03/26/maxwenzin/case-study-of-mobile-team-at-projectplace&quot;&gt;a blog post on the Crisp Blog about the challenges of a distributed Scrum Team&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Mon, 26 Mar 2012 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2012/03/26/challenges-of-a-distributed-scrum-team.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2012/03/26/challenges-of-a-distributed-scrum-team.html</guid>
        
        <category>agile</category>
        
        <category>scrum</category>
        
        
      </item>
    
      <item>
        <title>My first Visual Agenda inspired by Gamestorming</title>
        <description>&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/gamestorming-visual-agenda-by-max-wenzin-179x300.jpg&quot; alt=&quot;Visual Agenda by Max Wenzin&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/images/gamestorming-visual-agenda-by-max-wenzin.jpg&quot;&gt;Full image&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will be doing some blogging on the Crisp blog from now on.&lt;/p&gt;

&lt;p&gt;Here’s &lt;a href=&quot;http://blog.crisp.se/2012/03/22/maxwenzin/my-first-visual-agenda&quot;&gt;a post about my first Visual Agenda&lt;/a&gt;, inspired by the book Gamestorming.&lt;/p&gt;
</description>
        <pubDate>Thu, 22 Mar 2012 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2012/03/22/my-first-visual-agenda-inspired-by-gamestorming.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2012/03/22/my-first-visual-agenda-inspired-by-gamestorming.html</guid>
        
        <category>agile</category>
        
        
      </item>
    
      <item>
        <title>Reverse Phone Lookup in Google App Engine</title>
        <description>&lt;p&gt;&lt;img src=&quot;/images/google-app-engine.png&quot; alt=&quot;Google App Engine&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I wrote a small pet-project this weekend based on Java in Google App Engine.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;It’s a single-page web app that helps you use directory services (like white and yellow pages) in different countries. Ever needed to search for people in different countries? Hard to find which directory service to use? Well, this app solves that problem for you by knowing the best services and providing you with a single form to use, regardless of which back-end site will provide you with the search result.&lt;/p&gt;

&lt;p&gt;I havn’t quite named it yet. It started out with the sexy name “Reverse Phone Lookup”, but since most sites now allow searching for name or phone in the same field, that name was not really appropriate. It now has the totally generic and boring header: Global Directory Search. Yuck. Oh, well. You can reach the app at the following URL:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://reverse-phone-lookup.appspot.com/&quot;&gt;http://reverse-phone-lookup.appspot.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/betrcode/ReversePhoneLookup&quot;&gt;The source code is available at GitHub&lt;/a&gt; if you’d like to write some request, or contribute!&lt;/p&gt;
</description>
        <pubDate>Sun, 11 Mar 2012 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2012/03/11/reverse-phone-lookup-in-google-app-engine.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2012/03/11/reverse-phone-lookup-in-google-app-engine.html</guid>
        
        <category>java</category>
        
        <category>git</category>
        
        
      </item>
    
      <item>
        <title>Agile Change Strategies</title>
        <description>&lt;!--more--&gt;

&lt;p&gt;&lt;iframe style=&quot;overflow: hidden;&quot; src=&quot;http://www.mindmeister.com/maps/public_map_shell/144170886/change-strategies?width=515&amp;height=560&amp;z=0.5&amp;no_logo=1&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;515&quot; height=&quot;515&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;p&gt;Change Strategies by &lt;a href=&quot;http://crisp.se/henrik.kniberg&quot;&gt;Henrik Kniberg&lt;/a&gt;. Mindmap created in Mindmeister by &lt;a href=&quot;http://crisp.se/max.wenzin&quot;&gt;Max Wenzin&lt;/a&gt;. &lt;a href=&quot;https://www.mindmeister.com/144170886/change-strategies&quot;&gt;View full map in Mindmeister&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Change Strategies&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ask for foregiveness rather than permission
&lt;li&gt;Use metrics
&lt;li&gt;Reversible &quot;experiments&quot;
&lt;li&gt;Set an example
&lt;li&gt;Talk to everyone at once &amp; Capture the intent
&lt;li&gt;Visualize the current situation
&lt;li&gt;Compare options
&lt;li&gt;Make a business case for your change
&lt;/ul&gt;
&lt;/p&gt;
</description>
        <pubDate>Tue, 06 Mar 2012 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2012/03/06/agile-change-strategies.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2012/03/06/agile-change-strategies.html</guid>
        
        <category>agile</category>
        
        <category>scrum</category>
        
        
      </item>
    
      <item>
        <title>How-to do Sprint Planning using Jira</title>
        <description>&lt;p&gt;I have been using Jira for many years and have worked as a Scrum Product Owner for a few years. I have managed multiple teams, based in different parts of the world. This is my guide to using Jira as a Sprint Planning tool.
&lt;!--more--&gt;&lt;/p&gt;

&lt;h3 id=&quot;when-to-use-a-web-based-tool-instead-of-a-wall-board-whiteboard&quot;&gt;When to use a web-based tool instead of a wall board (whiteboard)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;When you have distributed teams&lt;/li&gt;
  &lt;li&gt;When you want to work on your tasks from multiple locations&lt;/li&gt;
  &lt;li&gt;When you need to share information with outside stakeholders (like customers)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have a simpler scenario, try using the simplest tool possible for your task tracking, like a whiteboard.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/jira-screenshot-300x258.png&quot; alt=&quot;Jira screenshot&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;before-sprint-planning&quot;&gt;Before Sprint Planning&lt;/h3&gt;
&lt;p&gt;It’s the job of the Product Owner to keep the Product Backlog groomed &amp;amp; ordered. The items on top of the backlog should be well enough specified so that they can be moved into a Sprint Backlog. This work is ongoing and often means talking to stakeholders a lot.&lt;/p&gt;

&lt;p&gt;Before Sprint Planning I prepare one Jira “bucket” per team. Usually I use one Jira “Version” for each Sprint and add a custom field (“Sprint Team”) to track which team a specific issue belongs to.&lt;/p&gt;

&lt;p&gt;I fill the buckets with issues I find suitable for each team until there’s more than enough issues for each team. How do I know how much is enough? Past performance. Do I have estimates on all issues? No, usually not. Perhaps on some.&lt;/p&gt;

&lt;p&gt;This results in a &lt;strong&gt;preliminary&lt;/strong&gt; Sprint Backlog. This is not the final Sprint Backlog, but only a suggestion.&lt;/p&gt;

&lt;p&gt;I usually juggle a bit with the ordering (prioritization) to make sure the most important issues are on top. Also, if there are any bigger or riskier issues, I move them up the list so they are handled early in the Sprint.&lt;/p&gt;

&lt;p&gt;A few days before the Sprint Planning meeting I send out links to the preliminary backlog to the teams. At this time, the suggestion for next iteration should be pretty stable, but changes can still occur.&lt;/p&gt;

&lt;p&gt;This enables the team to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Review the issues in advance (makes for a quicker and less painful Sprint Planning meeting)&lt;/li&gt;
  &lt;li&gt;Give me feedback on poor priotization, poor team choice etc&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;managing-left-overs&quot;&gt;Managing left-overs&lt;/h4&gt;
&lt;p&gt;Hours before the Sprint Planning meeting I kick any unfinished issues from the current Sprint into the preliminary Sprint Backlog for the upcoming Sprint. If there are issues that are not valid any more, I close them with “Won’t fix” or similar resolution. Issues that have been started are usually given a higher priority. (“Stop starting, start finishing”) The full remainder from current Sprint does not necessarily make it to the top of the list for the upcoming Sprint. Priorities change and new things pop up.&lt;/p&gt;

&lt;h3 id=&quot;during-sprint-planning-meeting&quot;&gt;During Sprint Planning meeting&lt;/h3&gt;
&lt;p&gt;It is the job of the Scrum Master to send invites to the Sprint Planning meeting. The Product Owner is just there to clarify the backlog and answer questions. I try to take a backseat position here if possible and let the team drive the planning as much as possible.&lt;/p&gt;

&lt;p&gt;Since the teams are often distributed in different parts of the world we usually use Skype for voice and some screen sharing software to display Jira.&lt;/p&gt;

&lt;p&gt;Quick overview of Sprint Planning process using Jira:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Display list of issues (preliminary Sprint Backlog) in Jira and talk about the overall goal of the Sprint&lt;/li&gt;
  &lt;li&gt;For each issue in the list:
    &lt;ol&gt;
      &lt;li&gt;Team reads the issue&lt;/li&gt;
      &lt;li&gt;Team discusses the issue and asks the PO when in need of clarification&lt;/li&gt;
      &lt;li&gt;Team estimates the issue using Planning Poker or similar technique. Estimation is entered as “Time Remaining” in Jira. (or if estimation is done in “Story Points”, in some other suitable Jira field)&lt;/li&gt;
      &lt;li&gt;When the team feels that they have enough issues to fill a Sprint, the process ends. This is usually done by summing up the “time remaining” on the issues in the Jira “bucket” and when that sum reaches what the team usually manages (their velocity), then they know they have enough. Please note that summing up “Original Estimate” is not a good idea if you have work-in-progress left-overs from last Sprint.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;after-sprint-planning&quot;&gt;After Sprint Planning&lt;/h3&gt;
&lt;p&gt;Directly after Sprint Planning I kick all issues that didn’t make the cut to the next version so that the teams bucket only contain what they have committed to for the new Sprint. Then I send a Jira link to the stakeholders so they can see exactly what the new Sprint Backlog contains. I may only send them a list of the issues that didn’t make the cut if I know they were expecting some specific issues.&lt;/p&gt;

&lt;p&gt;I usually have some Jira filters for each Sprint to make it simple for the teams to know what issues to work on. I update these for the new Sprint.&lt;/p&gt;

&lt;p&gt;Here are some example filter names:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Current Sprint - TODO - Team A&lt;/li&gt;
  &lt;li&gt;Current Sprint - TODO - Team B&lt;/li&gt;
  &lt;li&gt;Current Sprint - TODO - Team C&lt;/li&gt;
  &lt;li&gt;Current Sprint - TO TEST - Team A&lt;/li&gt;
  &lt;li&gt;Current Sprint - TO TEST - Team B&lt;/li&gt;
  &lt;li&gt;Current Sprint - TO TEST - Team C&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can probably figure out what these filters show…&lt;/p&gt;

&lt;h3 id=&quot;closing-thoughts-and-further-reading&quot;&gt;Closing thoughts and further reading&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/jira_admin_ninja_black.png&quot; alt=&quot;Jira Admin Ninja Black, courtesy of Atlassian&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I hope this guide gives you some idea how you can make it work. If you wish to read more about Jira in general, visit &lt;a href=&quot;https://www.atlassian.com/software/jira&quot;&gt;Atlassians Jira section&lt;/a&gt;. If you are unsure of the Scrum terminology used here, or just want to know more about Scrum, check out &lt;a href=&quot;https://www.scrumalliance.org/why-scrum&quot;&gt;What is Scrum at Scrum Alliance&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 21 Feb 2012 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2012/02/21/how-to-do-sprint-planning-using-jira.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2012/02/21/how-to-do-sprint-planning-using-jira.html</guid>
        
        <category>agile</category>
        
        <category>scrum</category>
        
        <category>jira</category>
        
        
      </item>
    
      <item>
        <title>Cheap Oracle virtualization</title>
        <description>&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Use multiple Oracle instances in the same machine instead of multiple virtualized hosts in the same machine.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/oracle-db-instances-279x300.png&quot; alt=&quot;Illustration of virtualization&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;/h2&gt;
&lt;p&gt;I read &lt;a href=&quot;http://computersweden.idg.se/2.2683/1.392449/kappahl-har-trottnat-pa-oracle&quot;&gt;an article in Computer Sweden today where Kappahl couldn’t do virtualization of their Oracle databases&lt;/a&gt; (article in swedish) because of expensive licence costs. In this article, I would like to offer a simple and cheap option to Oracle virtualization.&lt;/p&gt;

&lt;h2 id=&quot;why-virtualization&quot;&gt;Why virtualization?&lt;/h2&gt;
&lt;p&gt;Organizations want to virtualize their Oracle databases for many reasons, one being to reduce license costs. Other reasons include reducing hardware costs and making it easy to add new databases.&lt;/p&gt;

&lt;p&gt;Simply put, hardware virtualization is basically about exchanging many physical servers for a single big server.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/virtualization-212x300.png&quot; alt=&quot;Many small to one big&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You may prefer &lt;a href=&quot;https://en.wikipedia.org/wiki/Virtualization&quot;&gt;the wikipedia definition of virtualization&lt;/a&gt;, but mine is short, sweet and simple.&lt;/p&gt;

&lt;h2 id=&quot;the-alternative-solution&quot;&gt;The alternative solution&lt;/h2&gt;
&lt;p&gt;Instead of doing Oracle virtualization using VMWare or Oracle VM, you can install several Oracle instances in a single Oracle installation, in a single machine. This is not what people usually mean when they say virtualization, but you get many of the benefits this way, and it will reduce your Oracle license costs!&lt;/p&gt;

&lt;h3 id=&quot;pros&quot;&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Still easy to start/stop individual instances&lt;/li&gt;
  &lt;li&gt;Still easy to add/remove individual instances&lt;/li&gt;
  &lt;li&gt;Still easy to configure memory and disk usage per instance&lt;/li&gt;
  &lt;li&gt;No need to learn/buy any virtualization technique&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;cons&quot;&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;All instances will run on the same Oracle binaries, meaning all will run on the same Oracle version (some may consider this a benefit, when you’ve reached it…)&lt;/li&gt;
  &lt;li&gt;All Oracle instances will run on the same OS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;real-world-experience&quot;&gt;Real world experience&lt;/h2&gt;
&lt;p&gt;I have seen this work very well, especially for testing and development installations. Virtualization of databases in a production environment may not be as common, but there’s no reason it shouldn’t work there aswell.&lt;/p&gt;
</description>
        <pubDate>Tue, 21 Jun 2011 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2011/06/21/cheap-oracle-virtualization.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2011/06/21/cheap-oracle-virtualization.html</guid>
        
        <category>oracle</category>
        
        
      </item>
    
      <item>
        <title>Don't Repeat Yourself in PLSQL parameters</title>
        <description>&lt;!--more--&gt;

&lt;p&gt;When writing PLSQL in the Oracle database, you define parameters to a function/procedure like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;FUNCTION&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getFullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iUserId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;IN&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INTEGER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;RETURN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VARCHAR2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;IS&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;BEGIN&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--TODO: Implement this&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;RETURN&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;END&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getFullname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Instead of writing it like that, consider using a table.column definition as type for your parameter! This way, if you change your table, you will not also have to change your code!&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;FUNCTION&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getFullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iUserId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;IN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SIGNUP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;RETURN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VARCHAR2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;IS&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;BEGIN&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;--TODO: Implement this&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;RETURN&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;END&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getFullname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, if you for some reason change the ID column in the SIGNUP table to be something other than INTEGER, you can leave the code as is! Much more DRY!&lt;/p&gt;
</description>
        <pubDate>Mon, 25 Apr 2011 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2011/04/25/dont-repeat-yourself-in-plsql-parameters.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2011/04/25/dont-repeat-yourself-in-plsql-parameters.html</guid>
        
        <category>oracle</category>
        
        <category>plsql</category>
        
        
      </item>
    
      <item>
        <title>Unit testing pl/sql</title>
        <description>&lt;!--more--&gt;

&lt;h2 id=&quot;my-situation&quot;&gt;My situation&lt;/h2&gt;
&lt;p&gt;I currently have an assignment where there is a large PLSQL code base. It’s been developed actively for about 12 years and works quite well. I am not saying it’s flawless, but quite mature. There’s lots of room for improvement and lots of dead code that needs to be removed.&lt;/p&gt;

&lt;p&gt;Some of the plsql is called from the Java DAO layer of a front-end web application, but most of it is used for backoffice functionality. The parts that are accessed from the Java layer are tested through integration tests based on JUnit, but the large part that is only used from the backoffice has no unit test coverage.&lt;/p&gt;

&lt;h2 id=&quot;doing-something-about-it&quot;&gt;Doing something about it&lt;/h2&gt;
&lt;p&gt;I’ve known about the utPLSQL framework for many years, but never gotten around to actually use it in a Continuous Integration environment. I decided it was time to do something about it and started by adding the installation of utPLSQL to the already in place automated database reinstallation build. The installation part was quite easy, I just dropped the utPLSQL install scripts into our own source control repository and made it part of our db install. Uninstalling utPLSQL was a bit tricker since it creates public synonyms and those are not dropped when the Oracle db user/schema is dropped. (And that’s how we “uninstall” our other schemas normally.) And if I let those public synonyms stay there, I would get errors on the next install. So I simply need to create a small script that dropped those public synonyms as part of the uninstall/install (reinstall :) ) process.&lt;/p&gt;

&lt;p&gt;After utPLSQL was part of our db installation, I created a couple of sample utPLSQL tests and tried them out. No problems there. I could run them from the SQL prompt without problem. But what I really wanted was to make them part of the build process in Hudson. So I started writing a JUnit test that would wrap the utPLSQL tests and then it would be runnable from Hudson.&lt;/p&gt;

&lt;p&gt;After I while it struck me that I was writing something that someone else had probably written already and after a quick google I found the maven-utplsql-plugin. (insert holy graal sound here) Since we use Maven for the builds, this seemed like a perfect match. However, there were some pitfalls.&lt;/p&gt;

&lt;h2 id=&quot;some-pitfalls&quot;&gt;Some pitfalls&lt;/h2&gt;
&lt;p&gt;The maven-utplsql-plugin is currently not available in any public Maven repository. So, I had to download it and install it add it manually to our local Maven repo. The only problem was that our Maven repo was setup not to accept SNAPSHOT releases, and since we didn’t want to change that, I had to HACK the source files in the zip file and replace SNAPSHOT with STABLE in order for our Maven repo to accept the new artifact. In fact, this may lead to that I have to do some contributions to the dev team of the maven-utplsql-plugin to get it up to a RELEASE version and maybe even up on a public repository?&lt;/p&gt;

&lt;h2 id=&quot;the-happy-ending&quot;&gt;The happy ending&lt;/h2&gt;
&lt;p&gt;Finally, I added a new task to our db-reinstall profile in Maven. The new task simply calls the plugin which runs the tests. SUCCESS!&lt;/p&gt;

&lt;h2 id=&quot;my-sources&quot;&gt;My sources&lt;/h2&gt;
&lt;p&gt;Here’s the Maven plugin for utplsql: &lt;a href=&quot;https://sourceforge.net/projects/utplsql/&quot;&gt;https://sourceforge.net/projects/utplsql/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The utPLSQL project: &lt;a href=&quot;https://sourceforge.net/projects/utplsql/&quot;&gt;https://sourceforge.net/projects/utplsql/&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 23 Apr 2011 00:00:00 +0000</pubDate>
        <link>https://www.bettercode.se/2011/04/23/unit-testing-plsql.html</link>
        <guid isPermaLink="true">https://www.bettercode.se/2011/04/23/unit-testing-plsql.html</guid>
        
        <category>java</category>
        
        <category>oracle</category>
        
        <category>plsql</category>
        
        <category>testing</category>
        
        
      </item>
    
  </channel>
</rss>
