tag:blogger.com,1999:blog-36181784078534771792024-03-13T11:59:38.209+01:00Code CopFanatic About Code Quality Since 2004Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.comBlogger252125tag:blogger.com,1999:blog-3618178407853477179.post-16744993058036502592024-03-10T17:34:00.000+01:002024-03-10T17:34:09.376+01:00Programming with NothingI like extreme coding constraints. A constraint, also known as an activity, is a challenge during a kata, coding dojo or code retreat designed to help participants think about writing code differently than they would otherwise. Every constraint has a specific learning goal in mind, for example <a href="/2017/09/verbs-instead-of-nouns.html">Verbs instead of Nouns</a>. After playing with basic constraints for a long time now, I need more challenging tasks. Combining existing constraints makes things harder: For example <a href="/2018/01/compliance-with-object-calisthenics.html">Object Callisthenics</a> or my very own <a href="/2015/08/introducing-brutal-coding-constraints.html">Brutal Coding Constraints</a> are way harder than their parts applied individually.<br /><br />
<a href="https://www.flickr.com/photos/jyotsna_/8263281359/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 213px; text-align: center; border: 0;" src="//www.code-cop.org/images/Void.jpg" alt="Void (licensed CC BY-NC-ND by Jyotsna Sonawane)" title="Void (licensed CC BY-NC-ND by Jyotsna Sonawane)" /></a><!--
--><b>Missing Feature Group of Constraints</b><br />
There is a another group of extreme constraints which I call the <i>Programming With Nothing</i> constraints. They are a subgroup of the <i>Only Use <placeholder></i> constraints. All of these belong to the <i>Missing Feature</i> group. The well known <a href="/2014/11/tddaiymi-vs-naked-primitives.html">No If and No Naked Primitives</a> constraints are good examples of Missing Features because we take away a single element that we are so very much used to. Only Use <placeholder> constraints force you to use new constructs instead of something else. For example, <a href="https://alexbolboaca.ro/">Alexandru Bolboaca</a>, the pioneer of Coderetreat in Europe, once mentioned the following constraints to me: <i>Only Bit Operations</i> replaces all arithmetic operations, like plus or multiply, with bit operations and <i>Only Regular Expressions</i> asks you to use Regular Expressions as much as possible. You can get pretty far with Regular Expressions in exercises like Balanced Brackets, Coin Change, Snake or <a href="/2011/08/word-wrap-kata-variants.html">Word Wrap</a>. (Look for the Bonus Round at the bottom of the Word Wrap page.)<br /><br />
<b>Programming With Nothing</b><br />
But let us get back to <i>Programming With Nothing</i>. The first one of this group, which I came across ten years ago, was presented by Tom Stuart in his 2011 Ru3y Manor talk <a href="https://tomstu.art/programming-with-nothing">Programming With Nothing</a>. Tom is taking functional programming to the extreme, only allowing the declaration of lambda expressions and calling them. The exact rules he is following are:<!--
--><ul><li>Create functions with one argument.<!--
--></li><li>Call functions and return a result.<!--
--></li><li>Assign functions to names (abbreviate them as constants).<!--
--></li></ul><!--
-->Basically he is using the <a href="https://en.wikipedia.org/wiki/Lambda_calculus">Lambda Calculus</a> and this constraint is also referred to as <i>Lambda Calculus</i>. His talk is using Ruby, using only <code>Proc.new</code>, no booleans, numbers or strings, no assignments, control flow constructs or standard library. Clearly he is programming with nothing. (Here is the <a href="https://www.youtube.com/watch?v=VUhlNx_-wYk">recording</a> of the talk, his <a href="https://speakerdeck.com/tomstuart/programming-with-nothing">slides</a> and the <a href="https://github.com/tomstuart/nothing
">code</a>.) Over the years I have seen similar presentations, even using Java.<br /><br />
<b>The Fizz Buzz Kata</b><br />
The goal is to implement the Fizz Buzz kata. While Fizz Buzz is very simple, it needs looping integer numbers up to 100, conditionals on integer comparison, integer division and strings. It is very small but not simple. Some people even use it <a href="https://imranontech.com/2007/01/24/using-fizzbuzz-to-find-developers-who-grok-coding/">during job interviews</a> - which is controversial. The whole Fizz Buzz is:<!--
--><pre class="prettyprint lang-java">for (i = 1; i <= 100; i++) {
if (i % 3*5 == 0)
print("FizzBuzz");
else if (i % 3 == 0)
print("Fizz");
else if (i % 5 == 0)
print("Buzz");
else
print(i);
}</pre><!--
-->And this is quite a lot if all you have is a lambda. I maintain a <a href="https://github.com/codecop/FizzBuzz-with-Nothing-Kata">starting point for TypeScript</a>, to be used in my workshops. This kind of exercise is fun, at least for me ;-). If you follow the assignment, i.e. work on numbers, then booleans, then pairs etc., you can use Git branches to jump to the next milestone - or take a sneak peak how it could be done.<br /><br />
<a href="https://www.flickr.com/photos/foilman/3807122977/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 189px; text-align: center; border: 0;" src="//www.code-cop.org/images/NothingHappened.jpg" alt="Nothing Happened (licensed CC BY-SA by Henry Burrows)" title="Nothing Happened (licensed CC BY-SA by Henry Burrows)" /></a><!--
--><b>Extreme Object-Orientation</b><br />
In 2015 I watched John Cinnamond's <a href="https://www.youtube.com/watch?v=FDs-sSxo2iY">Extreme Object-Oriented Ruby</a>, which is like Tom Stuart's Programming with Nothing. This version only allowed you to define objects which contain other objects and call the nested object's methods or return them. In <a href="https://github.com/jcinnamond/oo-ruby">his starter repository</a> he described how to simulate booleans, numbers and so on.<br /><br />
<b>Nothing but NAND</b><br />
Then I tried to write Fizz Buzz only using <a href="https://en.wikipedia.org/wiki/NAND_gate">NAND</a>. This is Programming With Nothing the hardware way. How so? <i>A NAND gate is a logic gate which produces an output which is false only if all its inputs are true; thus its output is complement to that of an AND</i> says Wikipedia. More importantly, the <i>NAND gate is significant because any Boolean function can be implemented by using a combination of NAND gates. This property is called functional completeness.</i>. Because of its functional completeness it should be possible to create arbitrary programs. I started out with a <code>Bit</code> class which had its <code>nand()</code> function implemented and all other code was built on top of this. Numbers, i.e. arrays of bits,<!--
--><pre class="prettyprint lang-java">class Numbers {
static final Byt ZERO = new Byt(OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF);
// ...
static final Byt FIFTEEN = new Byt(ON, ON, ON, ON, OFF, OFF, OFF, OFF);
static final Byt HUNDRED = new Byt(OFF, OFF, ON, OFF, OFF, ON, ON, OFF);
}</pre><!--
-->and bitwise logic,<!--
--><pre class="prettyprint lang-java">class Logic {
static Bit eq(Bit a, Bit b) {
return not(xor(a, b));
}
// ...
static Byt and(Byt a, Byt b) {
return not(nand(a, b));
}
// ...
static Byt ifThenElse(Bit b, Byt theThen, Byt theElse) {
Byt condition = Byt.from(b);
return or(and(condition, theThen),
and(not(condition), theElse));
}
}</pre><!--
-->were straight forward. Arithmetic was cumbersome due to possible over- and underflows.<!--
--><pre class="prettyprint lang-java">class Arithmetic {
static BitOverflow inc(Bit b) {
return new BitOverflow(not(b), b);
}
static BitOverflow add(Bit a, Bit b) {
return new BitOverflow(xor(a, b), and(a, b));
}
// ...
static Byt inc(Byt a) {
BitOverflow r0 = add(a.b0, Bit.ON);
BitOverflow r1 = add(a.b1, r0.overflow);
BitOverflow r2 = add(a.b2, r1.overflow);
BitOverflow r3 = add(a.b3, r2.overflow);
BitOverflow r4 = add(a.b4, r3.overflow);
BitOverflow r5 = add(a.b5, r4.overflow);
BitOverflow r6 = add(a.b6, r5.overflow);
BitOverflow r7 = add(a.b7, r6.overflow);
return new Byt(r0.b,r1.b,r2.b,r3.b,r4.b,r5.b,r6.b,r7.b);
}
}</pre><!--
-->For loops I added a sequence of bits which worked as the <a href="https://en.wikipedia.org/wiki/Program_counter">Instruction Pointer</a>. Using the IP and the existing arithmetic operations I implemented <code>goto</code> which I used to jump back during loops. The final code did not look much different than your regular structural code, using functions and mutable data. The exact list of things I used was:<!--
--><ul><li>Data structures for a single bit, a byte (8 bits) and a series of bytes i.e. memory.<!--
--></li><li><code>Bit nand(Bit other)</code> as the only logic provided.<!--
--></li><li>Getting and setting the values of the data structures.<!--
--></li><li>Defining functions with multiple statements to create and modify data and call other functions.<!--
--></li><li>A map to associate statements with memory addresses indexed by the IP. Was this cheating?<!--
--></li></ul><!--
-->I had played with <a href="/2015/07/minesweeper-near-metal.html">assembly in the past</a>, which helped me to build my program from NANDs alone. It is a great learning exercise to understand computers' logical components and CPUs. There is even an educational <a href="https://store.steampowered.com/app/1444480/Turing_Complete/">game based on the idea of NAND</a>.<br /><br />
<b>What is Next?</b><br />
I cannot remember how I ended up there, but next I tried to write <!-- TODO link future post: touring -->Fizz Buzz using a Touring Machine. But this is a story for another time...
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-80113871475122181812023-10-19T12:42:00.000+02:002023-10-19T12:42:21.225+02:00Unit Testing SchemeFor more than four years this article has been waiting to be written. Now a rainy summer day can do wonders. Back in 2018, when <a href="/2018/12/scheme-programming-language.html">I fell into Scheme</a>, I needed a unit testing framework. I was digging into Scheme with coding exercises and wanted the quick feedback of my TDD cycle so see if I was on the right track. I did not know anything about modules, dependency management or how to get custom code in Scheme and searched the web for a small test framework. As minimalism is in the spirit of Scheme, I initially went with the <a href="http://wiki.c2.com/?SchemeUnit">Scheme Unit outlined on Cunningham's Wiki</a>,<!--
--><pre class="prettyprint lang-scm">;
; Unit test framework for scheme
; see http://c2.com/cgi/wiki?SchemeUnit
;
(define (report-error msg)
(display "ERROR: ")
(display msg)
(newline))
(define (assert msg b)
(if (not b)
(report-error msg)))</pre>
<b>Evolution</b><br />
Now that was minimalist indeed. But as good as it was, it lacked important features: I wanted more assertions, at least for all basic data types, and needed to see some colours. What is the point of a green bar, if it is not shown in green. I had created my own xUnit libraries before, one for good old <a href="/2010/02/turbo-pascal-prime-factors-kata.html">Turbo Pascal</a> and one for <a href="/2015/08/how-to-unit-test-assembly.html">assembly</a> (written in assembly - usually you would use C). While both were useful, I did not get famous for them, it seems that am focusing on "niche products" in the testing framework world. Creating my own xUnit was a kata in itself and always helped me while <a href="/2020/05/learning-yet-another-programming.html">learning a new programming language</a>.<br /><br />
I started adding more assertions already in 2015 and test cases in 2017. I kept extending it whenever I needed something new, always copying the latest file to the next code kata. In 2018 I decided to put my "SchemeUnit" up on GitHub under the name of <a href="https://github.com/codecop/assert-scm">assert-scm</a>. Now my tests, for example the tests for the <a href="https://github.com/emilybache/Parrot-Refactoring-Kata">Parrot kata</a>, look like<!--
--><pre class="prettyprint lang-scm">(include "assert.scm")
(include "parrot.scm")
(test-case "it gets the speed of an european parrot"
(assert= 12.0
(parrot-speed 'european-parrot 0 0.0 #f)))
(test-case "it gets the speed of an african parrot with one coconut"
(assert= 3.0
(parrot-speed 'african-parrot 1 0.0 #f)))</pre>
<b>Features of xUnit</b><br />
Which features are expected from a true xUnit framework? From my knowledge of JUnit, I derive the core elements of xUnit:
<ul>
<li>Assertions: First we need assertions. These are typically called <code>assertSomething</code>. Assertions are necessary to verify the actual result versus the expected one. If these values are not equal, the assertion should fail in some way. There should be assertions for equality of basic data types. In my Scheme xUnit there are <code>(assert-true actual)</code> and <code>assert-false</code>, <code>assert=</code> for integer numbers and symbols (and everything you can compare with <code>=</code> in Scheme), <code>assert-char=</code> and <code>assert-string=</code> for these primitives and <code>assert-inexact=</code> for floating point numbers which allows a delta for rounding errors. There are <code>assert-null</code>, <code>assert-not-null</code>, and more. As lists are the basic, all encompassing data structure in Lisp, and therefore Scheme, any testing framework for these languages needs support for comparing lists for equality: <code>assert-list=</code> and <code>assert-list-deep=</code> for flat and deep list comparison.<br /><br /></li>
<li>Failure Messages: Assertions need to fail with descriptive messages. For example, if two values <code>expected</code> and <code>actual</code> are not equal, I would like to see <i>"expected: <expected value> but was: <actual value>"</i>. I hate testing frameworks which just stop with "Assertion failed." Creating good messages gets more interesting when comparing lists as they can be of different length and nested. After assertions, this is the second important thing to have.<br /><br /></li>
<li>Test Cases: In xUnit, test cases are often a bit weird, as they are classes containing multiple methods. Each of these methods is an individual test case because during test execution the class is instantiated for each method. In some frameworks test methods are named <code>testSomething()</code>, or annotations or other markers are used. In frameworks without classes, e.g. Jest or Pytest, each test function is a test case. A test case has a name, often the name of the method, some arrange code, some logic and one or more assertions. Test cases should be run independently of each other and report success or failure individually.<!--
--><pre class="prettyprint lang-scm">(test-case "(test-case) allows several assertions"
(assert-true #t)
(assert-true #t))</pre>
will print <code>(test-case) allows several assertions .. <span style="color:green">OK</span></code>.<br /><br /></li>
<li>Ignoring Test Cases: Sometimes I want to ignore a certain test case. Most frameworks offer ways to do that, e.g. <code>@Ignore, @Disabled, @mark.skip</code> or using other markers. I like the Mocha way of replacing <code>it('')</code> with <code>xit('')</code> and went for a different function <code>ignored-test-case</code>:<!--
--><pre class="prettyprint lang-scm">(ignored-test-case "(ignored-test-case) is ignored, else it would fail"
(assert-true #f))</pre></li>
<li>Test Suites: Test suites are used to group test cases. Naturally these are Java classes, Python modules or Jest/Mocha <code>describe</code> blocks containing test methods. In Scheme 5 that would be files. Files can include other files which allows me to build arbitrary test suites. I rarely use test suites in any language, as I am running all tests most of the time.<br /><br /></li>
<li>Fixtures: Fixtures contain the necessary creation and release of resources needed for the test and make sure these are released even if the test failed. Older test frameworks allow <code>setup</code> and <code>teardown</code> methods or <code>@Before/@After</code> markers. Other approaches include injecting necessary dependencies, as for example JUnit 5 and Pytest do. Till now I did not need fixtures in my exercises. In small test sets, I am fine when tests stop at the first failing test.<br /><br /></li>
<li>Asserting on Exceptions: Few testing frameworks offer assertions for exceptions. For example in Java, before JUnit 5's <code>assertThrows</code>, there were <a href="https://blog.codeleak.pl/2013/07/3-ways-of-handling-exceptions-in-junit.html">5+ ways to test that a method threw an exception</a>. Maybe this is a special case, something that is rarely used. As I was building my assert-scm Scheme xUnit from scratch, I wanted to be sure the assertions work. How would I test for a failing assertion? I had to dig deeper into Scheme. Standard R5RS Scheme has no function to catch exceptions and different implementations handle this differently. <a href="http://gambitscheme.org/">Gambit Scheme</a>, the Scheme I started, offers some proprietary extension for exceptions, whereas <a href="https://www.call-cc.org/">Chicken Scheme</a>, another common Scheme, has some support for handling exceptions - called conditions. At least Chicken version 4 does, but it is outdated now. Portability is an issue between different Scheme implementations. It seems Scheme R6RS has standard support for exceptions, but its structure is way more complicated. I would like to avoid this for fun exercises.</li>
</ul>
If you are interested in features of xUnit and how to use them I recommend you work through my <a href="https://github.com/codecop/Unit-Testing-Koans">Unit Testing-Koans</a> exercises.<br /><br />
<b>Prime Factors</b><br />
Exploring a new language is incomplete for me, until there is a nice TDD, step by step implementation of the Prime Factors kata. It is my goto exercise and I am <a href="/2021/03/11-years-prime-factors-kata.html">collecting my Prime Factors solutions</a> - which usually look the same. Here are the tests:<!--
--><pre class="prettyprint lang-scm">(include "prime-factors.scm")
(include "../assert-r5rs.scm")
(test-case "one"
(assert-null (prime-factors 1)))
(test-case "two"
(assert-number-list= (list 2) (prime-factors 2)))
; ...
(test-case "nine"
(assert-number-list= (list 3 3) (prime-factors 9)))
(test-case "max"
(assert-number-list= (list 2147483647) (prime-factors 2147483647)))</pre>
which execute in assert-scm's GitHub build,<br /><br />
<img style="display: block; margin: 0px auto 0px; width: 379px; height: 225px; text-align: center; border: 0;" src="//www.code-cop.org/images/screens/assert-scm-prime-factors-test.jpg" alt="assert-scm Prime Factors Test" title="assert-scm Prime Factors Test" /><br />
and verify the code<!--
--><pre class="prettyprint lang-scm">(define (prime-factors n)
(test-candidate n 2))
(define (test-candidate n candidate)
(cond ((= n 1) (list))
((too-large? n candidate) (prime n))
((divides? n candidate) (keep-candidate n candidate))
(else (next-candidate n candidate))))
(define (too-large? n candidate)
(> candidate (sqrt n)))
(define (prime n)
(list n))
(define (divides? n candidate)
(= (modulo n candidate) 0))
(define (keep-candidate n candidate)
(append (prime candidate)
(test-candidate (/ n candidate) candidate)))
(define (next-candidate n candidate)
(test-candidate n (+ candidate 1)))</pre>
This is neat, isn't it? If you fancy playing with Scheme and do not want to miss unit tests, check out <b><a href="https://github.com/codecop/assert-scm">assert-scm, a minimalist unit test framework for Scheme R5RS.</a></b>
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-28060850169562637712023-10-03T21:20:00.000+02:002023-10-03T21:20:01.462+02:00I find your lack of tests disturbing<a href="//www.code-cop.org/download/I_find_your_lack_of_tests_disturbing.jpg"><img style="float: right; margin: 0px 0px 10px 10px; width: 240px; cursor: pointer; height: 192px; text-align: center; border: 0;" src="//www.code-cop.org/images/screens/I_find_your_lack_of_tests_disturbing.jpg" alt="I Find Your Lack Of Tests Disturbing" title="I Find Your Lack Of Tests Disturbing" /></a><!--
-->Classics never get old. Like with <a href="/2023/08/shut-up-and-write-test.html">Shut up and Write a Test</a>, I am reposting an old meme about lack of tests, see its preview on the right. Lack of tests is a direct result of not following the prior advice when to write tests. ;-) In many coaching discussions I need to fall back to the fundamental basics and I cannot allow such a gem to vanish. Usually <a href="//www.code-cop.org/download/I_find_your_lack_of_tests_disturbing.jpg">I find the lack of tests in my client's code base disturbing</a>.<br /><br />
<b>Origin</b><br />
The image was posted on <i>rubystammtisch.at</i>, a site which ceased to exist long time ago. I downloaded it at the 25th of March 2009 for a presentation held at the local user group. The meme is a variation of <a href="https://knowyourmeme.com/memes/darth-vaders-i-find-your-lack-of-faith-disturbing">Darth Vader's "I find your lack of faith disturbing"</a>, used as a phrasal template where "faith" is swapped with other words. Now that I have researched the origin of the image, I could re-create it using Meme generators. I will not, a classic is a classic. (And again, during writing a blog post, the process of writing is valuable and I learn on the way by organising and structuring the material. That is why I recommend <a href="/2014/02/write-about-what-you-do.html">writing as a learning and teaching activity</a> at the same time.) Unfortunately the original image is only 400 pixel width, printed versions will be fuzzy. It might use it on my upcoming Code Cop Veto Cards, similar to my <a href="/2023/03/exceed-me.html">Achievement Appreciation Cards</a>, as cards require smaller images with less detail.<br /><br />
<b><a href="//www.code-cop.org/download/I_find_your_lack_of_tests_disturbing.jpg">I find a lack of tests disturbing</a></b>.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-18863099622018297232023-08-19T12:42:00.000+02:002023-08-19T12:42:36.204+02:00Unusual Personal Branding<img style="float: right; margin: 0px 0px 10px 10px; width: 155px; height: 240px; text-align: center; border: 0;" src="//www.code-cop.org/images/photos/BrennstempelAlkT4.jpg" alt="Brennstempel ALK T4" title="Brennstempel ALK T4" /><!--
-->I like personal branding and use a lot of branded items. Besides my obvious Code Cop business cards, I use "Code Cop approved" buttons and stickers as giveaways. I wear my Code Cop shorts and hoodies when meeting new clients and when <a href="/p/public-speaking.html">speaking at conferences</a>. I enjoy keeping track of my reading progress using my Code Cop <a href="/2011/10/awesome-book-marks.html">hand crafted book marks</a>. What else could there be? After the <a href="/2019/10/code-cop-embroidery.html">embroidery prototype</a> I was looking for something new to add to my branding toolbox.<br /><br />
<b>Branding Iron</b><br />
I have no memory of how I ended up with the idea, but I got a Code Cop branding iron. No I do not own any cattle or sheep which I need to mark, but at least "branding iron", gives a new meaning to "developer branding". My branding iron, see its picture on the right, needs to be plugged into electricity to warm up and after ten minutes it is ready. I have no idea how I will use it professionally - I am not selling anything in wood crates that could be marked - but I have a lot of fun marking everything in the house: For example, all my Escrima sticks and tool handles are clearly Code Cop's now.<br /><br style="clear: right;" />
<img style="display: block; margin: 0px auto 0px; width: 500px; height: 375px; text-align: center; border: 0;" src="//www.code-cop.org/images/photos/BrandedSticks.jpg" alt="Code Cop Logo Branded Sticks" title="Code Cop Logo Branded Sticks" /><br />
<b>Medallion</b><br />
Later, after watching Netflix' The Witcher, I toyed with the idea of a Code Cop medallion, like Geralt is wearing. The Witcher's medallion is pretty large and has a raised and relief design, which means part of the silver wolf's head has a 3D effect. I searched online shops for some month for custom pendants. Most places offer two dimensional ones, using vector graphics to drive the cutting or engraving machine. I tested one such design with a simple pattern. The pendant was fine but it was too thin and flat for me. That was not what I had envisioned.<br /><br />
Eventually I found Lucas from <a href="https://www.valeriacustomjewelry.com/">Valeria Custom Jewellery</a> who offered similar custom pendants. He 3D printed a mold and casted silver to create the three dimensional form on top of a large medallion. He sent me several work in progress images to check. During the whole process the cost went over the top, as I wanted a certain (too) large size, then shipping and tax for goods from overseas added on top. The total cost makes me wary to wear it. Further my wife keeps reminding me that I am not a rapper with their oversized and lavish jewellery ;-) While I am not wearing it, my Code Cop medallion is my most favourite branded item, sitting on my work desk right in front of me.<br /><br />
<img style="display: block; margin: 0px auto 0px; width: 500px; height: 500px; text-align: center; border: 0;" src="//www.code-cop.org/images/photos/CodeCopMedallion.jpg" alt="Code Cop Logo Medallion" title="Code Cop Logo Medallion" /><br />
To make my medallion more "magic" like Geralt's one, I fancy some engraving at its flat, smooth back. Maybe some piece of source code that is of general significance? Which code would that be? Surely code like the <a href="https://github.com/chrislgarry/Apollo-11">Apollo-11 guidance system</a> or the <a href="https://github.com/lborgav/Historical-Source-Codes/tree/master/Linux%20Kernel%200.01">first Linux kernel</a> are relevant. There are some collections like <a href="https://computerhistory.org/playlists/source-code/">Computer History Museum's source code</a>. Usually these are many pages of assembly. As the medallion is small compared to that, the code would have to be really short, a few statements at most. Maybe I will go with Greg Walsh's famous <a href="https://en.wikipedia.org/wiki/Fast_inverse_square_root">Fast Inverse Square Root</a> calculation from Quake III source code: <b>0x5f3759df</b>.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-7374400412625244312023-08-01T13:52:00.001+02:002023-08-01T13:56:09.085+02:00Shut up and write a test!Due to the hype around ChatGPT I wanted to create this text with it. I failed. I tried several versions of different prompts, and also asked the Bing variant, but it failed to create any text I liked. It could not simulate my personal style. I should have to train a model with all my blog posts ... It seemed easier to use with the good old method of writing my texts myself.<br /><br />
<b>Should I Write a Test?</b><br />
Around ten years ago I stumbled upon a diagram if and when to write a test. This was a repeating question in trainings, when should you write tests? Before or after writing the code? Only when you have time? Only when you feel like it? I loved the diagram because there was only one end state. Whatever the reason or excuse would be, just <i>shut up and write a test!</i> It does not matter if you are tired, or if it is a little change, it should be tested. Such a rule is helpful when you want to adopt Test Driven Development, as there are <a href="/2019/08/y-u-no-tdd.html">plenty of excuses why to skip it</a>.<br /><br />
<a href="https://lancsrubygem.wordpress.com/2012/10/18/shut-up-and-write-a-test/"><img style="display: block; margin: 0px auto 0px; width: 395px; cursor: pointer; height: 321px; text-align: center; border: 0;" src="//www.code-cop.org/images/screens/shut-up-and-test.jpg" alt="Shut Up and Write a Test!" title="Shut Up and Write a Test!" /></a><br />
The original diagram was created by Gemma R Cameron, a software engineer and event organiser from Manchester. She was inspired by a similar diagram about skating. Recently, when I was asked again when to test, I wanted to share the diagram and could not find its page. I thought it lost and planned to repost the diagram here. Eventually I discovered Gemma's page again, it had moved from a <code>.me</code> to a WordPress domain. I am glad that the original source is still available. You can find it <a href="https://lancsrubygem.wordpress.com/2012/10/18/shut-up-and-write-a-test/">here</a>.<br /><br />
<b>Java Version</b><br />
The original version of the diagram was for Ruby, indicated by the use of Automock. What was bad with Automock? It provided some support for automated mocking of Rails application and is dead since 2016. Here I present a slightly <a href="//www.code-cop.org/download/shut-up-and-test-java.pdf">modified version for Java</a>, replacing Automock with <a href="https://github.com/powermock/powermock">PowerMock</a>. And I do know what is wrong with PowerMock. It is a powerful mocking tool which <i>uses a custom class loader and bytecode manipulation to enable mocking of static methods, constructors, final classes and methods, private methods and more.</i> It is useful to bring legacy code under test, before <a href="https://tobeva.com/articles/seams/">seams</a> can be introduced. The bytecode manipulation makes it slow compared to regular mocking. If used often, the whole test suite will run much longer than needed. Further, if code is hard to test, I change its design to make it testable by applying SOLID principles or by creating seams as outlined by Michael Feathers in his <a href="https://www.goodreads.com/book/show/18674867-working-effectively-with-legacy-code">WELC book</a>. Using PowerMock for tests does not improve the design. (I am not inherently against PowerMock, it is extremely powerful and as such dangerous. I needed something to replace Automock.)<br /><br />
Download and print the <a href="//www.code-cop.org/download/shut-up-and-test-java.pdf">Java version of the Shut up and Write a Test Diagram</a>. The fact that there are versions of this diagram for both Ruby and Java is a testament to the universality of its principle: <b>Shut up and Write a Test!</b> The Code Cop approves, and I am sure your future self will too.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-2223042990951977152023-03-15T16:43:00.003+01:002023-03-20T08:19:52.360+01:00I want you to exceed meDuring my <a href="/2012/01/code-cop-goes-blue.html">time at IBM</a> I started coaching other teams. It was fun and I liked it. Later I went into full time training and coaching<!-- TODO link future post: business -->, and my motto was "Developing Quality
Software Developers". I knew it was the thing I wanted to do, but I did not know why.<br /><br />
<b>Gamification</b><br />
I use Gamification as a strategy to improve user engagement. To increase participation in my workshops and to express my feelings about that, I created achievement cards, the Code Cop Achievement Cards<!-- TODO link future post: Achievement Cards -->. Achievements or trophies are concepts from video games, and describe <i>meta-goals defined outside the game's parameters. Meeting the fulfilment conditions, and receiving recognition of fulfilment by the game, is referred to as unlocking the achievement.</i> There are several cards for first time participants in my deck, for example <b>Shortcut Fu</b> when someone uses a rare keyboard short-cut, <b>Regexer</b> for comprehending a crazy regular expression or <b>Finisher</b> for finishing the coding exercise started during the workshop at home - which I always offer but rarely happens. I award these cards to a participant, if I feel that the person has worked hard or struggled to make it.<br /><br />
<b>Appreciation</b><br />
I wanted my cards to convey my honest appreciation and used NVC (Non-violent Communication) appreciation statements. For a <a href="https://ellyvanlaar.com/2015/11/27/appreciation-nvc-style-13/">NVC-style appreciation</a> <i>we share the specific actions that contributed to our well-being, the needs that have been fulfilled, and the feelings engendered by the fulfilment of those needs. The focus is to create a clear understanding of how our life was enriched.</i>. This made me think more about my feelings and which of my needs had been satisfied at the moments when I wanted to appreciate some action. I had <a href="/2019/09/human-needs-vs-bad-code.html">thought about needs before</a> in more general, less personal way. My friend and NVC coach <a href="https://twitter.com/rinkkasatiainen">Aki Salmi</a> helped me to formulate these statements using different phrases to avoid having the same text on each card again and again: For example: "I value the usage of short-cuts as effective and as sign of ongoing mastery in our craft." "I am touched to see courage in situations of uncertainty, risk and emotional exposure." "I am amazed by critical questions based on creativity and independent thought." "I am inspired by the integrity and consistency of sticking to principles in difficult situations." The process of finding the right words alone strengthened my ability to express my feelings dramatically.<br /><br />
<img style="float: right; margin: 0px 0px 10px 10px; width: 234px; height: 320px; text-align: center; border: 0;" src="//www.code-cop.org/images/photos/VeryPersonalAppreciationBadge.jpg" alt="Very Personal Appreciation Badge (copyright Peter Kofler)" title="Very Personal Appreciation Badge (copyright Peter Kofler)" />
<b>Scrutiny</b><br />
Some of my appreciation cards celebrate learning, including stepping out of one's comfort zone, which is required for learning. One card I of these is titled "Scrutiny", subtitled Correct me when I am wrong. It shows a <a href="https://game-icons.net/1x1/delapouite/whistle.html">Whistle icon</a> (by Delapouite <a href="https://creativecommons.org/licenses/by/3.0/">CC BY 3.0</a>) and the appreciation is "I am proud when you correct me, showing independence and competence." It does not happen often - still sometimes in a pairing or <a href="/2014/09/teaching-using-mob-programming.html">ensemble session</a>, my focus may slip and I make a mistake or do not call out a mistake on time. And then, sometimes, someone else does.<br /><br />
<b>Growth</b><br />
There is a common theme in most of my cards: growth. Now that I have seen it, it is obvious to me. Growth is one of my major needs. I want to grow - e.g. <a href="/2020/05/learning-yet-another-programming.html">learning new languages</a> and other stuff regularly. And I want the people I coach and work with to grow, too. My second motto - <a href="/p/journeyman-tour.html">surfacing around 2013</a> - "Developing Quality Software Developers" expresses that clearly. I want them to grow, to learn, to improve - and I am inspired and amazed the most, when they exceed me.<br /><br />
<b>Snatch the Pebble From My Hand</b><br />
There is nothing more satisfying than when a pupil exceeds his or her master. This is often depicted in movies, where a student must learn a lot, for example in Kung Fu movies: In the <a href="https://en.wikipedia.org/wiki/Kung_Fu_(1972_TV_series)">television series Kung Fu</a>, Caine is an orphan and is accepted into a Shaolin Monastery. Part of the Shaolin way of life is strengthening the body and the mind. For example, one of Caine's teachers asks him to "snatch the pebble from my hand":<br /><br />
<iframe style="DISPLAY: block; MARGIN: 0px auto 0px; WIDTH: 500px; HEIGHT: 282px" src="https://www.youtube.com/embed/9selPW2lL-M" title="Pebble from my hand" frameborder="0" allowfullscreen></iframe>
<!-- WIDTH: 789px; HEIGHT: 444px --><br />
Then, after many years of training, Caine is finally able to beat his master:<br /><br />
<iframe style="DISPLAY: block; MARGIN: 0px auto 0px; WIDTH: 500px; HEIGHT: 282px" src="https://www.youtube.com/embed/YzaWAEhFWpw" title="Caine finally snatches the pebble from master Kan" frameborder="0" allowfullscreen></iframe>
<!-- WIDTH: 789px; HEIGHT: 445px --><br />
What a satisfying moment, and Caine's master smiles. This is one of my favourite TV moments ;-) Like being corrected (see Scrutiny card above), "snatch the pebble from my hand" situations make me proud of my students.<br /><br />
<b>Make Me Look Like a Baby</b><br />
I want to leave you with a quote from a different and maybe more controversial source of motivation than Caine, ex Navy SEAL member <a href="https://en.wikipedia.org/wiki/Jocko_Willink">Jocko Willink</a>: <i>Don't try and be like me. Be better than me. Crush me. Make me look like a baby. That's what you do.</i> (<a href="https://youtu.be/YxZsXZeFU1A?t=814">Even better when he says it himself</a>.) - OK, maybe there is too much testosterone here ;-)
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-18640077904830596642022-09-01T13:13:00.001+02:002022-09-01T13:13:00.170+02:00Tips for Remote Work<a href="https://www.flickr.com/photos/blakespot/5707206515/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 239px; text-align: center; border: 0;" src="//www.code-cop.org/images/newlySetupOutdoorHomeOffice.jpg" alt="newly setup outdoor home office (licensed CC BY by Blake Patterson)" title="newly setup outdoor home office (licensed CC BY by Blake Patterson)" /></a><!--
-->During COVID lockdown, I worked remotely. I did all my <!-- TODO link future post: business -->Code Cop things, e.g. pair programming, code reviews, coding workshops, just in a remote way. All these tasks involved other people and I was severely affected by my "remoteness". After one year of remote work, one of my clients ran an in-house knowledge sharing on how to do that successfully. They invited me and I thought about the advice I would give. What would be my top three tips for remote work?<br /><br />
<b>1. Check-in</b><br />
When working remotely, the first and foremost thing I use are check-ins. During a check-in everybody says a few words how he or she is here - as a human being. The check-in is not about your role, your expectations or current work. It is about how you feel. When we work separately, I miss your face and body language and we need to be explicit how we are. In a face to face situation I might be able to recognise if you are tired or distracted or upset. I am unable to identify the little hints when you are just a small image on my screen. Now I place more emphasis on the human and emotional side of my peers because it is missing in a remote setting. Some people always reply with "I am OK" and I am fine with that. Nobody has to share. Some people keep talking and I have to remind them what the check-in is about and stop them from taking all the space. Conversation, arguing or discussion break the check-in. And at the end of the meeting I ask everybody to check-out, which is the opposite, asking how they are leaving as human beings.<br /><br />
<b>2. Be Professional</b><br />
I preach being professional. After all "I help development teams with Professionalism" (as written on the second introduction slide of <a href="/2022/07/moving-away-from-slideshare.html">all of my decks</a>). Professionalism is an attitude, it is how you do your job. This includes also your appearance. In a remote setting, your appearance is the image of your face, the sound of your voice and the background behind your head. There are several implications: Your camera is always on. You are in the centre of your camera's focus and the camera is ideally placed on top of your screen where you are looking at from time to time. On the other hand, when only half of your face is visible, or your face is distorted in some way, it is hard to see and to connect. In communication theory, as the initiator if the exchange, the sender is responsible for the message to be received. Much of your message is conveyed by your voice. For the best audio, use a headset with a microphone so your team mates have a change of hearing you. Next I recommend a professional background. Best is a uniform wall or board. In the beginning of remote work, I hung a blanket between two window handles to provide a uniform, non distracting background during my video calls. Non uniform backgrounds are distracting and make it harder to focus on the face of the person speaking. A Green Screen background helps if you have no option to work in front of a wall or door. Please choose a neutral image with soft colours. Most Green Screen backgrounds are unsuitable.<br /><br />
<a href="https://www.flickr.com/photos/princetoncrew/2229172061/"><img style="float: left; margin: 0px 10px 10px 0px; width: 320px; cursor: pointer; height: 213px; text-align: center; border: 0;" src="//www.code-cop.org/images/2VHvy07.jpg" alt="2VHvy07 (licensed CC BY-NC-ND by Princeton University Rowing)" title="2VHvy07 (licensed CC BY-NC-ND by Princeton University Rowing)" /></a><!--
--><b>3. Strive for the same Level of Collaboration</b><br />
It is harder to collaborate under remote working conditions. For example pair programming is more complicated. Now I do not accept less collaboration than before remote work. There are options and tools to overcome the barrier. Ten years ago, in 2012, I already used tools as TeamViewer or AnyDesk to control the machine of my <a href="/2012/08/remote-pair-practice.html">remote pairing partner</a>. I spent many hours working like that and it worked well. Modern tools I have used include <a href="https://www.jetbrains.com/code-with-me/">Code With Me</a>, which works with the JetBrains family of IDEs, <a href="https://visualstudio.microsoft.com/de/services/live-share/">Visual Studio Live Share</a>, which you can even join with a browser, Floobits, CodeTogether and <a href="https://mob.sh/">mob.sh</a>. If you are blocked by remote work, push for some solution to keep in touch and do what you used to do. Do not accept less collaboration than in face to face situations.<br /><br />
<b>We need to keep in touch</b><br />
After I had put together my three tips, I was surprised. I had expected some technology or tool but all three tips are about connecting. Then it is not a surprise after all, because remote work first and foremost affects collaboration. Most advice of the other presenters was aligned with that. Here are some examples: When working closely with a team you need to keep in touch. You should speak with your team members often, probably talk daily. You should also meet outside work, e.g. remote game events like online escape room. Meeting in person is even better, e.g. visiting each other or visiting the office once in a while.<br /><br />
<b>Video Conference All Day</b><br />
A team lead shared his story how they had managed transition to remote work. The team used to talk a lot during the day. When remote work started, they kept a video call running. Whenever people would work, they would be in the call, unless they were in a meeting with someone. Many team members used a second device, e.g. a tablet, for this ongoing call. They felt like being in the office and whenever someone wanted to talk, she could talk to the people in the room. Using the video conference open all day, the team kept up the good vibe while fully working remotely.<br /><br />
I am curious about your tips to improve remote collaboration. If you have any, I invite you to comment.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-87031267178692057142022-08-25T10:42:00.001+02:002022-08-25T10:42:43.855+02:00Practice SpeedSeveral years ago I co-facilitated the Global Day of Coderetreat with <a href="https://www.linkedin.com/in/hfakih/">Houssam Fakih</a>. It was a nice Coderetreat. During the introduction Houssam presented the concept of practice and three levels of competence. The first level is that you are able to do a certain thing from time to time. The second level is that you are able to do it all the time. The third level is, and that was new to me, that you perform the thing consistently well and fast at the same time. In this <a href="http://m.9gag.com/gag/abZRMMv">short video</a> there are three guys throwing balls at a boot at a fair. The guy on the right is on level one. He is able to throw the ball into the basket most of the time. The guy in the middle is competent and always hits the target. But the guy on the left is on another level. Besides hitting the basket consistently, he is using both hands alternating and is two to three times faster.<br /><br />
<a href="https://www.flickr.com/photos/warchild13/2927649822/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 181px; text-align: center; border: 0;" src="//www.code-cop.org/images/TheWalkToSaveGreatDanes.jpg" alt="The Walk to Save Great Danes (licensed CC BY-NC-ND by Warchild)" title="The Walk to Save Great Danes (licensed CC BY-NC-ND by Warchild)" /></a><!--
--><b>Deliberate Practice</b><br />
In Coding Dojos and Coderetreats we practice all kind of coding techniques like Test Driven Development, software design and pair programming, but we rarely practice speed. The <a href="https://coderetreat-facilitation.code-cop.org/2020/03/coding-dojo-mindset-and-game-of-life-is.html">Coding Dojo mindset</a> is explicit about going slow. There are a few exercises which have a timing aspect, e.g. <a href="https://medium.com/@olivercecilspann/elephant-carpaccio-exercise-an-experience-report-207f0cc79c34">Elephant Carpaccio</a> or <a href="https://blog.adrianbolboaca.ro/2013/03/taking-baby-steps/">Baby Steps</a>. Some people try to master the Baby Steps constraint by typing faster and using more shortcuts. While these are good things to practice by themselves, they bypass the exercise. Both exercises focus on taking smaller steps. The speed of typing is not the bottleneck.<br /><br />
<b>Side Note: Speed of Typing</b><br />
If the speed of typing is not the bottleneck in writing software, why do we focus on shortcuts and <a href="/2016/07/improving-typing-accuracy.html">touch typing</a>? The idea is, while coding, to stay in the flow and work on a higher level of abstraction. For example, when I want to move a method, and I can do it with a few keystrokes, I keep the current thoughts in my mind. But if I have to navigate, modify blocks of text, change method invocations, and so on, I think in more low level concepts like text editing or file navigation, and this breaks my focus.<br /><br />
<b>Hackathon</b><br />
One of my recent Coding Dojos became a Hackathon. A misunderstanding with the sponsor, who cared for food during the event, caused this. The sponsor wanted to run some challenge to make people think outside of the box, and make them try something new and innovative. They had prepared an assignment in Hackathon style. A <a href="https://tips.hackathon.com/article/what-is-a-hackathon">Hackathon</a> is <i>an event that brings together experts and creates a collaborative environment for solving a certain problem.</i> I avoid Hackathon because the format is competitive and people try to go as fast as possible to create some prototype or try to prove some idea or deliver some working code. Going fast above all else, e.g. skipping preliminary design or tests due time pressure is <a href="https://blog.cleancoder.com/uncle-bob/2013/03/05/TheStartUpTrap.html">the startup trap</a>. Obviously I dislike this way of working. (I see value in Hackathon as a tool for innovation and maybe team building.)<br /><br />
First I was unsure how to proceed. On one hand I wanted to please the sponsor, paying real money for the crafters community is a real contribution and separates the "talking" from the "doing" companies. On the other hand I wanted to stay true to the Coding Dojo experience. I thought of Houssam and remembered that going fast is a skill, one we need and rarely practice. In fact it is a skill we developers are often asked to apply, e.g. when the deadline is coming up or marketing has some new urgent idea. Like the guy on the left in Houssam's video, working fast and clean at the same time is hard. I made it a mix: I ran a Coding Dojo where the challenge was to finish some basic code in a given time frame. All Coding Dojo rules applied, the goal of the evening was to learn, to collaborate and to be nice. Even under pressure I reminded the participants to write tests because "your best code does not help you if it is broken". I encouraged them to work in small batches as "the most clever algorithm loses if it is unfinished". As facilitator I focused on helping people to create small, working increments. It worked well and after 90 minutes most teams had a working solution and three of them won a price.<br /><br />
<a href="https://www.flickr.com/photos/8628950@N06/1332225362/"><img style="float: left; margin: 0px 10px 10px 0px; width: 320px; cursor: pointer; height: 240px; text-align: center; border: 0;" src="//www.code-cop.org/images/Speed.jpg" alt="Speed (licensed CC BY by Gabriel)" title="Speed (licensed CC BY by Gabriel)" /></a><!--
--><b>How to Practice Speed</b><br />
Considering my own, personal practice, I go in the same direction. I am practising a lot on <a href="/2021/03/11-years-prime-factors-kata.html">old</a> and <a href="/2021/04/my-code-katas.html">new exercises</a>, in various programming languages, some I have much experience and some I <a href="/2020/05/learning-yet-another-programming.html">just learned</a>. Working these exercises, adding hard or even <a href="/2015/08/introducing-brutal-coding-constraints.html">brutal constraints</a> is boring. I even tried contradicting constraints like <!-- TODO link future post: constraint TDA and immutable -->Tell Don't Ask and Immutability. To try something new I started working against the clock. Maybe I can be the guy on the left.<br /><br />
<b>Roman Numerals</b><br />
My colleagues tell me that I am very fast in perceiving, reading and understanding code, as well as typing with shortcuts. When working against the clock my first exercise was <a href="https://codingdojo.org/kata/RomanNumerals/">Roman Numerals</a>. I chose a small exercise because I expected to retry it a lot. I set a timer to five minutes and worked on the kata. When the timer rang I stopped and analysed my progress. Of course I failed to finish but I kept trying. Some rarely used editing shortcuts would have helped, and I <a href="/2016/01/ide-shortcut-flashcards.html">learned some more of them</a>. I did use TDD and three to four tests were the most I was able to get, which was enough. The test for Roman <i>I</i> created the method <code>arabicToRoman</code>, <i>II</i> added a recursive call, <i>VI</i> introduced a lookup for the literal by its value and <i>388</i> introduced all the remaining literals. When using Ruby for the same exercise I thought I would be able to beat my Java time, because Ruby is more expressive and there is less code to write. Unfortunately I am not as familiar with Ruby as I am with Java and the missing code completion slowed me down. Currently I need five minutes for a fully working Arabic to Roman Numerals conversion including subtractive forms. I am able to create good names and small methods in the given time, but I am unable to create more elaborate structures for holding the Roman literals and their values. Java is just too clunky. In short: the code is good, but the design is bad.<br /><br />
<b>What Next</b><br />
Then I tried the Coin Changer kata and after several tries I was able to beat four minutes. Coin Changer and Roman Numerals are much alike and Coin Changer is simpler as it has no literals, the coin value is also the returned value. I knew both katas well, and the exercise was in fact only about my typing supported by tests to avoid mistakes. Maybe I should try a larger assignment. Running through many repetitions would be tedious. Maybe I should try unknown exercises. At least they would be unknown for the first run. I need a large number of little TDD exercises of similar size and complexity. Time to do some searching.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-15251136647520857292022-07-14T22:21:00.000+02:002022-07-14T22:21:09.263+02:00Moving away from SlideShare<a href="https://www.flickr.com/photos/8069051@N06/12540423063/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 214px; text-align: center; border: 0;" src="//www.code-cop.org/images/lostPlayground.jpg" alt="lost playground (licensed CC BY-SA by liebeslakritze)" title="lost playground (licensed CC BY-SA by liebeslakritze)" /></a><!--
-->One of <a href="/2014/04/how-to-divide-learning-time.html">my learning activities</a> is watching recordings of conference presentations, especially ones which have been recommended by <a href="/p/code-cop-approved.html">trusted colleagues and peers</a>. (You can find presentations which I recommend myself on <a href="https://www.youtube.com/playlist?list=PLYQPkkfIypvApLa4HZXNOdabdoYN-qzcz">YouTube</a> and <a href="https://vimeo.com/codecop/likes">Vimeo</a>.) After watching I usually download the slides and store them in my knowledge base, together with notes I might have taken during the presentation. At the moment my software development knowledge base is around 6G text files and PDFs, but that is a topic for <!-- TODO link future post: how to keep track of things -->another time.<br /><br />
From time to time I <a href="/p/public-speaking.html">present at conferences</a> or run a Coding Dojo. Afterwards I want to share my slides and I want you to be able to download them. In 2013 I started <a href="/2013/03/moved-to-slideshare.html">using SlideShare</a> for that. I liked it and it worked well. It organised my slides and added the social aspect on top, e.g. I connected with other people sharing slides and kept track of <a href="https://www.slideshare.net/pkofler/favorites">favourites</a>. Since Scribd acquired SlideShare I am not satisfied any more. I am facing technical problems uploading new slides again and again which is frustrating. Additionally downloading slides seems to require a paid membership. While I understand that free services need money to operate, I really want my slides to be available for download.<br /><br />
So I am moving away from SlideShare, or at least I am duplicating it. I did not follow my own <a href="/2015/06/choose-your-development-services-wisely.html">advice to avoid third party SaaS</a> - and as in the past I have to deal with the consequences now. I uploaded all slides I had shared on SlideShare to <a href="//www.code-cop.org/presentations/">my own folder</a> on my web space. It is just a folder and not as fancy as SlideShare, but you can <b><a href="//www.code-cop.org/presentations/">download</a></b>! Enjoy my slides.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-87667936569407082642022-02-26T12:49:00.004+01:002022-06-25T22:29:42.893+02:00Porting RLE8I am going back in time (again) and playing with some of my old source code: In the days of MS-DOS, <a href="https://en.wikipedia.org/wiki/16-bit_computing">16 bit</a> operating systems and <a href="https://en.wikipedia.org/wiki/Conventional_memory">640 kB of RAM</a>, I created a whole bunch of <a href="/2008/07/dos-tools.html">MS-DOS utilities and tools</a>, mostly written in <a href="/2010/02/turbo-pascal-prime-factors-kata.html">Turbo Pascal</a>. In the last 20 years I have only ported a few of them. From time to time I miss one of these old tools - but never miss it enough to invest the time to write it from scratch. Last year I came across <a href="http://users.fred.net/tds/lab/p2c/">p2c, a Pascal to C translator</a> by Dave Gillespie. Oh such joy - and I used it to port my old tools. One tool I used - which I had not created myself - was RLE8 by Shaun Case, Public Domain 1991.<br /><br />
<a href="https://www.flickr.com/photos/45359240@N02/8234728216/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 212px; text-align: center; border: 0;" src="//www.code-cop.org/images/artModerne.jpg" alt="art Moderne (licensed CC BY-NC-ND by Nadine)" title="art Moderne (licensed CC BY-NC-ND by Nadine)" /></a><!--
--><b>RLE8</b><br />
RLE stands for <b>r</b>un-<b>l</b>ength <b>e</b>ncoding compression. It is a form of data compression in which repeated values are represented by a count and a single instance of the value. It is a very simple form of compression and in the nineties it sometimes reduced disk and memory space significantly. It was used in early versions of Windows BMP for <a href="https://docs.microsoft.com/en-us/windows/win32/gdi/bitmap-compression">bitmap compression</a> named <code>BI_RLE8</code>: An RGB format that used run-length encoding (RLE) compression for bitmaps with 8 bits per pixel. The compression used a 2-byte format consisting of a count byte followed by a byte containing a colour index. There were versions for 4 and 8 bit image data, RLE4 and RLE8 respectively. "RLE compression was used in the stone-age" as one forum comment reads and today there not much interest in it. The only reference I found was for <a href="https://encode.su/threads/3168-rle8-A-fast-8-bit-RLE">benchmarking highly optimised code</a>.<br /><br />
<b>Finding the Original Source</b><br />
Finding the original source code was difficult. It is in the nature of the modern WWW that new pages appear and old ones disappear. Fortunately the <code>RLE8.EXE</code> printed the name of its author and its license: <i>Shaun Case 1991 Public Domain</i>. After some googling I found an <a href="https://archive.gamedev.net/archive/reference/articles/article291.html">article about it</a>, which later turned out to be the contents of the Readme someone had reposted almost ten years later on GameDev. Eventually I found <a href="http://www.retroarchive.org/">the Retro Computing Archive</a> with its collection of CD-ROMs containing shareware and Public Domain software from the late 80's and 90's. <a href="http://annex.retroarchive.org/cdrom/640_studio_iv/CLANG/RLE8_SC/index.html">RLE8_SC</a>. Win! (The Retro Computing Archive is great, many of its ZIP files are unpacked and therefore crawled by Google which helped me find it.)<br /><br />
<b>Porting from Turbo C</b><br />
The code compiled without issues, but included a header I did not have, <code>dir.h</code>, a header from Borland's Turbo C. I guess this is the biggest issue when porting old code - calls to non-standard library functions. I missed <code>fnsplit</code>, a function which split file specifications into component parts. While I could have created the function myself - <a href="/2020/05/learning-yet-another-programming.html">an excellent opportunity to practice my C</a> - I searched more and luckily <a href="https://github.com/vbs100/c-snippet/blob/master/fnsplit.c">someone had created it already</a>. Thank you Robert B. Stout. Robert granted <a href="https://github.com/vbs100/c-snippet/blob/master/license.mfl">license to use his source files to create royalty-free programs</a>, which RLE8 is. After adding some more of Robert's code, and removing code which was not needed, RLE8 compiled and linked, even with my pedantic settings of <code>gcc -std=c99 -pedantic -pedantic-errors -Wall -Wextra</code>. I loved it. Witness the power of C, a 50 years old programming language, still moving forward.<br /><br />
<a href="//www.code-cop.org/download/RLE8_by_Shaun_Case.zip">Download original and modified sources together with binaries for DOS and Windows x86</a>.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com1tag:blogger.com,1999:blog-3618178407853477179.post-22147802319417734282021-09-03T10:18:00.000+02:002021-09-03T10:18:40.329+02:00Baby Steps Push ChallengeEarlier this year I met with fellow developers <a href="https://twitter.com/rolgerm">Roland Germ</a> and <a href="https://twitter.com/bastien_david">Bastien David</a> to discuss how we could make coding exercises more engaging and how participants would have more fun. The training formats we use, like Coding Dojo and Coderetreat, were designed for people to have fun (and engage in deliberate practice in order to improve their skills). Ideas like gamification came to mind and we worked on several constraint games to spice up our coding sessions. (A constraint is an artificial challenge during an exercise to make the exercise more interesting, challenging or fun. I like constraints, e.g. my recent <a href="/2021/02/dice-namer-constraint.html">Dice Namer Constraint</a>. In this article I will describe another fun constraint: the Baby Steps Push Challenge.)<br /><br />
At the same time I was working with a client who was adopting Continuous Delivery. One of the issues the developers faced was that they were used to work in larger increments. We had worked through several exercises which encouraged smaller steps, e.g. <a href="http://blog.adrianbolboaca.ro/2013/03/taking-baby-steps/">Taking Baby Steps</a> (revert the code if tests are failing after 2 minutes), <a href="https://medium.com/@kentbeck_7670/test-commit-revert-870bbd756864">Test Commit Revert</a> (revert the code if tests are failing at any time) and even <a href="https://medium.com/@kentbeck_7670/limbo-on-the-cheap-e4cfae840330">Limbo</a> (revert the code if integration with other code fails). I was looking for more exercises to encourage small steps.<br /><br />
<a href="https://www.flickr.com/photos/marine_corps/25686193850/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 180px; text-align: center; border: 0;" src="//www.code-cop.org/images/LetSlipTheTugsOfWar.jpg" alt="Let Slip the Tugs Of War" title="Let Slip the Tugs Of War" /></a><!--
--><b>Idea of Push Championship</b><br />
Following my discussion with Roland and Bastien I merged some of their ideas into a "Push Championship" - a challenge who would be able to deliver smaller increments.
<ul><li>For this exercise I would need some basic TDD or Refactoring exercise.
</li><li>Pairs would work on the same task on their own using version control with branches.
</li><li>While dealing with merge conflicts is part of trunk based development, there should be no artificial branching problems. Participants just try to make more commits.
</li><li>All commits must be green which is tested by CI - actually it is much easier to count the number of successful build actions on each branch.
</li><li>The facilitator ("referee") needs to grade commits afterwards to avoid cheating the game and awards bonus points for good commit messages.
</li><li>Elements of gamification like coins for each commit/push would be nice.
</li></ul>
<b>Infrastructure</b><br />
I created some infrastructure to support the exercise. First there is a central server to count pushes and display the dashboard of positive and negative events during such a "championship": <a href="https://github.com/codecop/push-counter">Push Counter Server</a>. It has "Push" in its name but it is more general and can be used to count any form of positive (counting up) or negative (counting down) event. The server application is published on <a href="https://hub.docker.com/repository/docker/codecop/push-counter">Docker Hub</a>. You can run it with <code>docker run -p4567:4567 codecop/push-counter</code> and the dashboard will be available at <code>http://localhost:4567</code>. You can deploy it to Heroku, which I did. (<code>scripts/heroku_deploy</code> does the job - you need to change the Heroku application name.)<br /><br />
<b>Counting Pushes</b><br />
The server dashboard displays the current game statistics of all teams - that is the number of positive events - and <a href="https://freesound.org/people/steaq/sounds/387232/">plays a coin sound</a> (if you allow your browser to do so) when someone scores a point. To notify the server I execute <code>curl</code> at the end of a GitHub build action, e.g. <code>curl -X GET ${{secrets.PUSH_COUNTER_URL}}/​record/team-name?​build=green</code>. Whenever someone pushes to the repository, GitHub runs its build action and the dashboard gets updated.<br /><br />
<b>Distinguishing Pairs</b><br />
The easiest way to distinguish participant pairs is to use branches. In a scenario where each pair works the same exercise, this works well. I figure out the branch name with some shell and Git commands:
<pre>export GIT_BRANCH_NAME=$(git symbolic-ref --short HEAD)
export GIT_BRANCH_NAME=$( echo "$GIT_BRANCH_NAME" | sed 's/ /%20/g' )
curl -X GET ${{ secrets.PUSH_COUNTER_URL }}/record/branch-$GIT_BRANCH_NAME?build=green</pre>
The <a href="https://github.com/codecop/push-counter-client">Push Counter Sample Client</a> contains samples with several ways to identify pushes:
<ul><li>Using the branch name as shown above. This is dynamic and can be used for pairs working on branches.
</li><li>Hardcoding the branch name in the GitHub action also needs dedicated branches.
</li><li>Reading a team name from a file, i.e. using a lookup file on each branch is also possible.
</li><li>When working trunk based, the GitHub user who pushed can be used (i.e. <code>$GITHUB_ACTOR</code>). This works if pairs do not switch machines.
</li><li>Using a team name lookup by the GitHub user works also when pairs switch machines. Setup of the user name to team name mapping is necessary before the challenge.
</li><li>Using the GitHub user of the last commit is also possible.
</li><li>See the <a href="https://github.com/codecop/push-counter-client/blob/master/.github/workflows/java-count-pushes.yml">GitHub workflow file</a>.
</li></ul>
<b>Test Run</b><br />
When I tested the setup, I used - you guessed it - <a href="/2021/03/11-years-prime-factors-kata.html">my favourite Prime Factors kata</a>. The final score on the dashboard was:<br />
<img style="display: block; margin: 0px auto 0px; width: 462px; height: 95px; text-align: center; border: 0;" src="//www.code-cop.org/images/screens/PrimeFactorsScore.jpg" alt="Prime Factors score" title="Prime Factors score" />
<b>Choice of Kata</b><br />
Because of the competition, all participants should be able to finish coding, i.e. it should be possible to finish the exercise in one hour (as part of a workshop or learning hour). Refactoring exercises are a good choice because the given test suite makes sure only working changes/ pushes contribute to the total score. Unfortunately most refactoring exercises are larger than one hour. Then the goal of the refactoring needs to be more specific.<br /><br />
<a href="https://github.com/emilybache/Parrot-Refactoring-Kata">Emily Bache's Parrot Refactoring Kata</a> is a suitable exercise: It is small. (I am able to finish it on my own in less than 20 minutes. In fact - with some practice - I can run through its steps in less than 10 minutes.) And it has many steps, especially if you aim for baby steps. I counted 48 individual changes you can make - and I even missed a few. The concrete task here is to fix the code smell of switch on type code and clean up the code using as many individual, working refactoring steps as possible. Each commit should be delivered (pushed). And then you can repeat the exercise and try to break the score.<br /><br />
Other suitable refactoring exercises might be <a href="https://github.com/wouterla/TopGearKata">Top Gear</a> and <a href="https://github.com/dkandalov/promotion-service-kata">Promotion Service</a> from <a href="/2021/04/my-code-katas.html">my own list of code katas</a>.<br /><br />
<b>Coding Dojo Run</b><br />
Later I ran the exercise in our local Coding Dojo community. I showed some <a href="https://www.slideshare.net/pkofler/coding-dojo-baby-steps-push-challenge-2021">slides</a> to motivate small increments and gave some hints how to make smaller steps. I prepared a <a href="https://github.com/codecop/Parrot-Refactoring-Kata/tree/push-challenge">branch of Parrot</a> which reported to my Heroku dashboard. All went as planned and here is some of the feedback I got from participants in the retrospective:
<ul><li>The kata (parrot) was the right size, we had plenty of time to work carefully.
</li><li>We had to perform the same change three times - for the three sub-types - and used different approaches for each of them and compared them in the end. That was a bonus.
</li><li>We thought about "How small is small enough?"
</li><li>It is always possible to go smaller - you <i>can</i> commit more often.
</li><li>The constraint encouraged us to take much smaller steps than usually.
</li><li>Very small steps require lots of communication.
</li><li>Very small steps can become confusing due to the pause in between steps.
</li><li>I liked the dashboard and its icons.
</li><li>It would be nice to sit in the same room with the dashboard on a big screen.
</li><li>This notion of scoring works well in teams which have a good relationship.
</li></ul>
<b>Your Turn</b><br />
Now it is your turn to work the exercise. You do not need the server infrastructure if you are on your own. Just clone the parrot and see how many small steps you can make. Then try again and improve your score. Some participants were able to make 52 meaningful, tiny changes to the Parrot using Java. Try to break this high score. Everything above 40 is good and above 50 is very good. If you want to use the exercise for a Coding Dojo, fork the prepared <a href="https://github.com/codecop/Parrot-Refactoring-Kata/tree/push-challenge">branch of Parrot</a> and set the repository secret <code>PUSH_COUNTER_URL</code> to your dashboard. Have fun!<br />
<img style="display: block; margin: 0px auto 0px; width: 670px; height: 190px; text-align: center; border: 0;" src="//www.code-cop.org/images/screens/FinalScoreAfterReview.jpg" alt="Final score after review" title="Final score after review" />
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-81756795577723096672021-06-14T16:07:00.001+02:002021-06-14T16:07:38.826+02:00The One ThingLast year, during second lockdown, I watched a message of my guro Jakob where he proposed reading some books in the time when you are not able to practice in the dojo. He specifically recommended two books, <a href="https://www.goodreads.com/book/show/16256798-the-one-thing">The One Thing: The Surprisingly Simple Truth Behind Extraordinary Results</a> and <a href="https://www.goodreads.com/book/show/40121378-atomic-habits">Atomic Habits: An Easy and Proven Way to Build Good Habits and Break Bad Ones</a>. I had seen both books in my <a href="https://www.goodreads.com/author/show/16095826.Peter_Codecop_Kofler">Goodreads feed</a> and had not paid attention. But when your master asks, you better follow ;-)<br /><br />
<a href="https://www.flickr.com/photos/toolstop/4546017269/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 218px; text-align: center; border: 0;" src="//www.code-cop.org/images/Focus.jpg" alt="Focus" title="Focus" /></a><!--
--><b>The Book</b><br />
The book is about <i>extraordinary results determined by how narrow you can make your focus</i>. Gary Keller insists that it is possible to reach any goal if you focus on it. And by focus he means that you <i>really</i> focus i.e. dedicate four hours of each day to your one goal. It has to be one single goal. And then, by the thousands of hours you have put into your goal, you will see results. Yes obviously, when following this approach, you will see results. In this sense, the One Thing is extraordinary and boring at the same time. I highly recommend reading it.<br /><br />
First I planned to summarise the book for you, and others have done a better job doing that. The <a href="https://www.the1thing.com/">book's homepage</a> is a start and you can find many summaries of the book online, like <a href="https://fourminutebooks.com/the-one-thing-summary/">this one on Four Minute Books</a>. While summaries are short and save time, you will not get the benefit of the book without reading it. A book is not only about its content. Here the book is cementing its message by many times the author tells you the same thing in different words, a.k.a. repetition. The total time it takes to read the book is also time you have to reflect on the material.<br /><br />
<b>Impact</b><br />
Maybe my summary above is a bit lame, so let's discuss the book's impact on my life. And it had a profound impact as you will see. The first and utmost thing I remember from reading the book is the <i>permission to drop stuff from my agenda</i>. Like all developers I know, my daily plan was way too full: <!-- TODO link future post: work as Code Cop -->work, write a blog post like this one, release an episode of the <a href="https://coderetreat-facilitation.code-cop.org/">Coderetreat Facilitation podcast</a>, run a public Coding Dojo for the community, follow up on this cool idea I read about, finish reading <a href="/2018/12/scheme-programming-language.html">SICP and get back playing with Scheme</a>, create more <a href="/p/my-code-katas.html">exercises for workshops</a>, keep up to date with Twitter and other feeds, work out, spend time with family, fix this next thing in the flat my wife is complaining about, <!-- TODO link future post: XR -->fight climate change and much more. How was I supposed to allocate 4 (FOUR!) hours each day for the thing I want to do? It was impossible. Obviously Gary was crazy. ;-) Or I had to drop some tasks from my agenda.
The idea of focus and dropping tasks was not new to me. I remembered J.B. Rainsberger mentioning a <a href="https://laptrinhx.com/you-ain-t-gonna-do-it-1190324554/">"Not Doing" column</a> in his task list in 2014. I myself have put whole technologies on my blacklist - which I would ignore from this time on, but I have never dropped tasks and ideas so aggressively. I had <!-- TODO link future post: how to keep track of things -->several TODO lists of low priority where tasks went to die without being honest to myself.<br /><br />
<b>The First Month</b><br />
I spent the first month following the One Thing on a meta level because I did not work on anything but worked on the process itself. First I increased my focus: I deleted most icons - usually things to do or bookmarks to look at - from my desktop. I removed TODO markers in documents and on my hard drive. Then I reduced my commitments, e.g. I dropped the schedule to blog and record, stopped visiting meetups, reduced the <a href="/2017/04/33-days-of-education.html">number of learning hours</a> and decided on the maximum number of hours I would work for each client per week. And I was OK with that. Letting go became a mental state and I had been following <a href="https://www.theminimalists.com/">the Minimalists</a> and Marie Kondo already before I started.<br /><br />
Suddenly I had more time - I even had some unscheduled time to play video games which I almost never did. In hindsight this was not extraordinary at all. If you drop most things you are working on, you will have more time available. It is a matter of focus. Lockdown and home office helped as I saved more than two hours every day. While some colleagues complained that they worked two hours more, I used these two hours - giving me half of my required four hours already. And I used the first month - 80 hours total - to practice the One Thing process. I started each day with a few minutes of mediation to improve my focus. I read more books about focus, e.g. <a href="https://zenhabits.net/focus-book/">Leo Babauta's book on focus and simplicity</a>, forming habits, e.g. Atomic Habits as mentioned above and learning. I studied these books, taking notes and collecting them. I recommend all of them. I clean up my "office" and spent some time decluttering it, storing stuff in drawers or trashing it to further improve my focus during work.<br /><br />
<b>Books</b><br />
One example of my achievements since I started using the One Thing methods are the books I have been able to read this year. The Pragmatic Programmers once wrote that you should read at least four technical books a year and the last year I was able to follow their rule was 2016. Since then I have been struggling to read at least one technical book a year. Reading became hard, I had problems focusing and I usually fell asleep after reading a few pages. I decided to add some reading time every day to my four hours of focused work, reading on the topic of focus of course. So including the One Thing, I have read ten books in five months.<br /><br />
<a href="https://www.flickr.com/photos/sunnyuk/4745767752/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 213px; text-align: center; border: 0;" src="//www.code-cop.org/images/Archer.jpg" alt="Archer" title="Archer" /></a><!--
--><b>Clarity</b><br />
Spending four hours on focused work each day reduced the time I had available for other things. After some struggle, I had more clarity - and stopped my self-deception. For example, if I see an interesting article linked on Twitter I either read it immediately, or I forget about it. There is no point in adding it to my read-later list, because there is no read later list because there is no extra time for that. I would not read it anyway, my read-later list kept growing and growing. While I was dreaming of doing so much in the past, I have become a naysayer now. For example "this is a good idea. I might try it. (One second later.) No, not really this is not my One thing and I have no time. End of idea." This is refreshing and freeing. Clarity is one of <a href="/2019/09/human-needs-vs-bad-code.html">my needs</a>.<br /><br />
<b>Crunch Time</b><br />
One drawback is that I am always in crunch time. As my time is more limited, I have to prioritize harder and postpone many tasks I know I need to do. This makes me feel uneasy at times. And for the things I still want to do - not as my One thing, but from time to time, e.g. maintaining my blog - I have to live with tiny increments. For example, I was working on this blog post 15 minutes at a time for more than a month. It was a bit frustrating. Still <a href="/p/developer-branding-and-career.html">writing and "Public Relations"</a> are not my priority.<br /><br />
<b>Sorrow</b><br />
Not having time to attend meetups caused some FOMO (fear of missing out) and made me miss the people of the community I had not seen in a while. In general being unable to do things which I liked mad me sad. I have been attending every one
of our local, bi-monthly Coderetreats since its inception January 2019. When I was unable to attend for the first time in more than two years, I felt very, very sad. I felt a loss, almost like mourning. Maybe this was the first time in my life when I really let something go. It is easy to let go things you are not attached to.<br /><br />
<b>Crunch Time Summary</b><br />
Time for a very short summary (as my latest 15 minutes increment is almost spent): Read the book. Find your One Thing. Focus on it. It is possible to allocate four hours each day to focus on your highest priority, though it might be hard to stick to it. I am half a year into the process and did not miss a single day. <a href="/2018/09/work-harder.html">Keep pushing</a>!
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-11808219276500349572021-04-29T23:13:00.000+02:002021-04-29T23:13:23.809+02:00My Code Katas<a href="https://www.flickr.com/photos/thadz/24017883478/"><img style="float: right; margin: 0px 0px 10px 10px; width: 320px; cursor: pointer; height: 214px; text-align: center; border: 0;" src="//www.code-cop.org/images/AscendingTheStairs.jpg" alt="Ascending the Stairs" title="Ascending the Stairs" /></a><!--
-->I run various trainings for software developers, at least one every week. I have used many different exercises - called code katas - most of them curtesy of my fellow coaches, especially Emily Bache who maintains a huge collection of excellent exercises on <a href="https://github.com/emilybache">her GitHub</a>. And I created some exercises myself. I have <a href="/p/my-code-katas.html">collected all of them on a page</a>, each with a short description how to use it. Enjoy!<br /><br />
Check out <a href="/p/my-code-katas.html">My Code Katas (permanent link)</a>.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-58984934608198796112021-03-20T00:49:00.004+01:002023-10-19T12:55:20.321+02:0011 Years of Prime Factors KataIn this post I want to celebrate the Prime Factors Code Kata. Prime Factors is a small coding exercise <a href="http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata">first used by Robert C. Martin in 2005</a>. It is my favourite code kata and it has been almost nine years since I last wrote about it - time to change that. Weird enough, the first code kata I ever worked on - outside of university assignments that turned out to be katas later - was <a href="https://codingdojo.org/kata/RomanNumerals/">Roman Numerals</a> in 2007. The first time I did the Prime Factors was during Christmas holidays 2009 in Java and Ruby:<!--
--><pre class="prettyprint lang-java">import java.util.ArrayList;
import java.util.List;
public class PrimeFactors {
public static List<Integer> generate(int n) {
List<Integer> primes = new ArrayList<Integer>();
for (int candidate = 2; candidate <= n; candidate++) {
for (; n % candidate == 0; n /= candidate) {
primes.add(candidate);
}
}
return primes;
}
}</pre><!--
-->Now the Java code is exactly the code Robert Martin showed, I was following his example. The Ruby version from back then looks pretty similar, just using <code>while</code> instead of <code>for</code>.<!--
--><pre class="prettyprint lang-rb">
module PrimeFactors
def generate(n)
prime_factors = []
candidate = 2
while n > 1 do
while n % candidate == 0 do
prime_factors << candidate
n /= candidate
end
candidate += 1
candidate = n if candidate > Math.sqrt(n) # performance fix
end
prime_factors
end
end</pre><!--
-->If you are wondering how I am still able to find the code, <a href="/2015/05/how-to-organise-your-code-katas.html">I organise my code katas to allow lookup and comparison</a>. Since then I did the kata <b>141</b> times and it has many uses.<br /><br />
<b>Learn a language</b><br />
Prime Factors is one of the first pieces of code I write - Test Driven of course - when revisiting old languages, like <a href="/2010/01/prime-factors-kata-basic.html">Commodore BASIC</a> or <a href="/2020/05/learning-yet-another-programming.html">looking at a new language</a>, like <a href="/2011/02/ultraedit-and-gforth.html">Forth</a>, using Gforth 0.7:<!--
--><pre>: prime_factors <span class="com">( n -- n1 n2 n3 n4 )</span>
DUP 1 > IF <span class="com">\ test for ?DO</span>
DUP 2 ?DO
BEGIN
DUP I MOD 0 = <span class="com">\ test candidate I</span>
WHILE
I SWAP I / <span class="com">\ add candidate, reduce number</span>
REPEAT
LOOP
THEN
DUP 1 = IF DROP THEN ;
T{ 1 prime_factors -> }T
T{ 2 prime_factors -> 2 }T
T{ 3 prime_factors -> 3 }T
T{ 4 prime_factors -> 2 2 }T
T{ 6 prime_factors -> 2 3 }T
T{ 8 prime_factors -> 2 2 2 }T
T{ 9 prime_factors -> 3 3 }T</pre><!--
-->Gforth came with a modified testing framework based on John Hayes S1I's <code>tester.fs</code>, defining the functions <code>T{</code>, <code>-></code> and <code>}T</code> for testing. Note that the given function <code>prime_factors</code> is not realistic as the number of returned arguments is not known by the caller.<br /><br />
When <a href="/2009/03/start-scala.html">I had a look at Scala</a>, of course I did Prime Factors:<!--
--><pre class="prettyprint">import java.lang.Math.sqrt
object PrimeFactors {
def generate(number: Int): List[Int] = {
def fold(current: Pair[Int, List[Int]], candidate: Int): Pair[Int, List[Int]] = {
if (current._1 % candidate == 0)
fold((current._1 / candidate, candidate :: current._2), candidate)
else
current
}
val (remainder, factors) =
(2 to sqrt(number).intValue).foldLeft((number, List[Int]()))(fold)
if (remainder > 1)
(remainder :: factors).reverse
else
factors.reverse
}
}</pre><!--
-->This is crazy. The code creates a sequence of all candidate primes and folds it starting from left by dividing by the candidate recursively, appending to the begin of the list, which is cheap. Because of that the list is reversed at the end. I have no idea why I created this, probably I was playing around with <code>foldLeft</code>. This is not a good example, please do not copy it. After all these years, the Forth solution seems easier to grasp. ;-)<br /><br />
So which languages are missing? PowerShell looks much like my PHP (shown below) and my Python Prime Factors looks similar too, just with Python specific <code>range(2, number + 1)</code> and <code>//=</code> inside. And of course JavaScript is missing:<!--
--><pre class="prettyprint lang-js">PrimeFactors = function() {
this.factors = [];
};
PrimeFactors.prototype.generate = function(num) {
var candidate;
for (candidate = 2; candidate <= num; candidate += 1) {
num = this.tryCandidate(num, candidate);
}
return this.factors;
};
PrimeFactors.prototype.tryCandidate = function(num, candidate) {
while (num % candidate === 0) {
num = this.reduceByFactor(num, candidate);
}
return num;
};
PrimeFactors.prototype.reduceByFactor = function(num, factor) {
this.factors.push(factor);
return num / factor;
};</pre><!--
-->Isn't that lovely? Again this is not good code, please do not copy it. At least I showed some creativity using prototype functions.<br /><br />
<b>Learn a testing framework</b><br />
Using TDD to write some known code is a perfect way to learn more about a testing framework. So <a href="/2012/03/prime-factors-xslt.html">I explored XSLTunit using Prime Factors in XSLT</a> or <a href="https://nunit.org/">NUnit</a> in C#:<!--
--><pre class="prettyprint lang-cs">using NUnit.Framework;
[TestFixture]
public class PrimeFactorsTest
{
[TestCase(new int[0], 1)]
[TestCase(new int[] { 2 }, 2)]
[TestCase(new int[] { 3 }, 3)]
[TestCase(new int[] { 2, 2 }, 4)]
[TestCase(new int[] { 2, 2, 2 }, 8)]
[TestCase(new int[] { 3, 3 }, 9)]
public void TestFactors(int[] expected, int number)
{
CollectionAssert.AreEqual(expected, PrimeFactors.Generate(number));
}
[Test]
[Timeout(100)]
public void TestLarge()
{
CollectionAssert.AreEqual(new int[] { int.MaxValue },
PrimeFactors.Generate(int.MaxValue));
}
}</pre><!--
--><b>Test your own testing framework</b><br />
Sometimes, when I need to create my own unit testing framework, e.g. <a href="/2010/02/turbo-pascal-prime-factors-kata.html">TPUnit for old Turbo Pascal</a>, <a href="/2023/10/unit-testing-scheme.html">assert-scm</a> (Scheme R5RS) or <a href="/2015/08/how-to-unit-test-assembly.html">ASM Unit</a> for Windows Assembly, I use Prime Factors as test cases:<!--
--><pre>_prime_factors:
mov esi, 0 <span class="com">; esi = number of factors</span>
mov edi, ebx <span class="com">; edi = address of factors</span>
mov ecx, eax <span class="com">; ecx = current number</span>
mov ebx, 1 <span class="com">; ebx = candidate</span>
jmp .not_diviseable
.loop_over_candidates:
inc ebx <span class="com">; next candidate</span>
.break_if_candidate_is_larger_than_square:
<span class="com">; if candidate * candidate <= number then try candidate</span>
mov eax, ebx
mul ebx
cmp eax, ecx
jbe .try_candidate
<span class="com">; else number is a (large) prime and we are done</span>
mov [edi + esi * register_size], ecx
add esi, 1
jmp .done
.try_candidate:
<span class="com">; if number % candidate == 0 then add candidate</span>
mov eax, ecx
xor edx, edx
div ebx
cmp edx, 0 <span class="com">; remainder is 0</span>
jne .not_diviseable
.is_diviseable:
mov [edi + esi * register_size], ebx
<span class="com">; store candidate in factors</span>
add esi, 1 <span class="com">; we found a factor</span>
mov ecx, eax <span class="com">; number is remainder of division</span>
jmp .try_candidate <span class="com">; try current candidate again</span>
.not_diviseable:
<span class="com">; if number > 1 then try next candidate</span>
cmp ecx, 1
jne .loop_over_candidates
.done:
<span class="com">; return number of factors</span>
mov eax, esi
ret</pre><!--
-->This piece of assembly calcultes the prime factors of the number passed in <code>EAX</code> into in the dword array address <code>EBX</code>.<br /><br />
<b>TDD Demo</b><br />
In 2012 I started practising Prime Factors as <a href="https://8thlight.com/blog/micah-martin/2013/05/28/performing-code-katas.html">kata performance</a>, minimising the number of keys I pressed. I ran it around 50 times. In the end I used the practice to calm down when I was anxious - it was like mediation. I still have to perform it somewhere, adding music and all... I have used it demoing TDD in uncounted presentations - actually around 40: during my <a href="/2010/12/code-quality-assurance-v2.html">university guest lectures</a>, user group meetings and at my clients. Most demos were in Java and some in PHP,<!--
--><pre class="prettyprint"><?php
class PrimeFactors {
static function generate($n) {
$factors = [];
for ($candidate = 2; $candidate <= $n; $candidate += 1) {
while ($n % $candidate == 0) {
$factors[]= $candidate;
$n /= $candidate;
}
}
return $factors;
}
}</pre><!--
-->and a single demo of test driving R code,<!--
--><pre class="prettyprint">
primeFactors <- function(number) {
factors <- vector(mode="integer")
candidate <- 2
while (candidate <= sqrt(number)) {
while (number %% candidate == 0) {
factors <- c(factors, candidate)
number <- number / candidate
}
candidate = candidate + 1
}
if (number > 1) {
factors <- c(factors, number)
}
factors
}</pre><!--
-->It seems, most programming languages look the same. The last sentence is not true for <a href="/2018/07/using-natstyle.html">NATURAL</a>, Cobol's cousin, which is ugly. I will not show it here as it would destroy this lovely post.<br /><br />
<b>Conclusion</b><br />
By writing this post, I learned that I still need to create Prime Factors in the programming languages Go, Kotlin, OpenOffice Basic, Oracle PL/SQL and of course TypeScript - I could - and I will, it is just a matter of time. So Prime Factors - in fact any small enough code kata - is a great tool for exploring, studying and practising programming languages, testing frameworks, IDE tools and Test Driven Development in general. I will leave you with my latest addition to my collection of Prime Factors, using C99. Have fun!<!--
--><pre class="prettyprint">#include <math.h>
typedef struct {
unsigned char count;
unsigned int values[31];
} PrimeFactors;
void PrimeFactors_init(PrimeFactors* factors)
{
(*factors).count = 0;
}
void PrimeFactors_add(PrimeFactors* factors, const unsigned int factor)
{
int count = (*factors).count;
(*factors).values[count] = factor;
(*factors).count = count + 1;
}
void generate(const unsigned int number, PrimeFactors* factors)
{
PrimeFactors_init(factors);
unsigned int remaining = number;
for (unsigned int candidate = 2; candidate <= sqrtl(remaining); candidate += 1) {
while (remaining % candidate == 0) {
PrimeFactors_add(factors, candidate);
remaining /= candidate;
}
}
if (remaining > 1) {
PrimeFactors_add(factors, remaining);
}
}</pre>
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com2tag:blogger.com,1999:blog-3618178407853477179.post-53982869977964745372021-02-17T23:33:00.002+01:002021-08-24T14:16:05.924+02:00Dice Namer ConstraintA constraint is an artificial challenge during an exercise to make the exercise more interesting, challenging or fun. I like constraints and <a href="/search/label/constraint">wrote about some of them</a>. The Dice Namer is such a constraint: <i>Everything but the names of test methods is named using random dices.</i> The French company <a href="https://www.arolla.fr/">Arolla</a> created some really nice dices using random, enterprise-y useless names like <i>Processor, Dummy</i> or <i>Factory</i>. I managed to get several sets and to use them in my coding exercises after discussing naming in code. Now with the remote work due to Covid, I had to come up with something new. And here it is, the<br /><br />
<a href="/p/arolla-dice-namer.html">Arolla Dice Namer Application</a><br /><br />
Press the buttons and see the random dices for your name, together with some dices-like sound (if you allow your browser to play it). This is a real fun and it will help you create amazing code like this one using viciously named functions...<br />
<a href="https://twitter.com/codecopkofler/status/928780102028201984"><img style="display: block; margin: 0px auto 0px; width: 748px; cursor: pointer; height: 577px; text-align: center; border: 0;" src="//www.code-cop.org/images/screens/WhatDoesThisCode.jpg" alt="What does this code do?" title="What does this code do?" /></a>
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-45818153388331380832021-02-01T21:06:00.000+01:002021-02-01T21:06:49.508+01:00Working with AI SurveillanceSince several years I am exploring <a href="/2015/10/work-with-meaning.html">ethics and meaning of my work as software engineer</a>. While it is not a clear cut topic, it lies in the core of our work, similar to all the tech and engineering stuff. Last year Artur Meyster, CTO of <a href="https://careerkarma.com/">Career Karma</a>, contacted me about cooperating on a guest blog post here on my site. (Thank you Artur for your patience.) While guest blogging seems mainly SEO related, I do not mind a fresh perspective on a topic I have been thinking about, much like the <a href="/search/label/interview">series of interviews</a> I am conducting from time to time. This post was mostly written by Maria Elena Gonzalez. Maria is a broadcast journalist and has been working as a tech writer for three years. During this time, her work has been published by companies like TechAccute, Trip University, and Entrepreneur - and now by the Code Cop ;-)<br><br>
<a href="https://www.flickr.com/photos/simonjtp/9274163875/"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 205px; TEXT-ALIGN: center" src="//www.code-cop.org/images/HeavySurveilance.jpg" alt="Heavy Surveillance" title="Heavy Surveillance" border="0" /></a><!--
--><b>AI Surveillance</b><br>
The recent evolution of technology has resulted in many new areas, such as data science, virtual reality or machine learning. As a developer, these are the new and cool topics to explore and dive into. (Maybe start with a <a href="http://studydatascience.org/">data science boot camp</a>.) Applications in these areas have improved our quality of life. They serve the same purpose as AI surveillance: to improve our quality of life. However, as is the case with any invention, AI surveillance has a dark side: we might be losing our right to privacy.<br><br>
You may think this is a problem only for famous people, but that is not the case. It can also be a problem for you. According to a recent <a href="https://carnegieendowment.org/2019/09/17/global-expansion-of-ai-surveillance-pub-79847">report from the Carnegie Endowment for International Peace</a>, 75 out of 176 countries are using Artificial Intelligence (AI) for surveillance purposes, which makes it hard to know who is safe from AI surveillance. If you would like to know more about the impact of AI surveillance on our daily life, read on.<br><br>
<b>What is AI Surveillance?</b><br>
AI surveillance goes beyond <a href="https://en.wikipedia.org/wiki/Artificial_intelligence_for_video_surveillance">AI-driven security cameras</a>. Companies and governmental organizations have been using this technology to track trends and transitions to make better business decisions.<br><br>
<b>How is it Affecting Us?</b><br>
AI surveillance has many benefits. For example, it can improve traffic. Have you ever waited for traffic lights to turn green even though there are no cars around? This could be improved by using AI surveillance. AI algorithms can detect movement and change traffic lights phasing based on real-time activity. Financial companies can use AI surveillance to spot malicious activities and minimize fraud. This has the potential to revolutionize the financial industry. The possibilities are endless, and we could continue to show you the positive aspects of AI surveillance, but let's take a look at the darker side.<br><br>
With the amount of data collected increasing rapidly, the possibility of privacy invasion is rocketing. While some AI surveillance activity falls within the law, others represent privacy violations. <a href="https://www.privacyinternational.org/">Privacy International</a> points out that AI surveillance can be very delicate when it comes to data privacy: "With the proliferation of surveillance cameras, facial recognition, open-source and social media intelligence, biometrics, and data emerging from smart cities, the police now have unprecedented access to massive amounts of data." Governments that take advantage of this technology have access to citizens' personal data, a situation that can quickly turn into a violation of privacy rights if left unchecked.<br><br>
<b>Which Countries are Adopting AI Surveillance Technology?</b><br>
Among the leaders in the use of AI surveillance are China and the United States. Out of the two, China is implementing the technology more widely. According to the Carnegie Endowment for International Peace, the organizations that most often use AI surveillance are part of the government. China is not only using the technology to improve traffic, it is also applying AI surveillance to track the activities of the Uighurs, in the northwestern province of Xinjiang, <a href="http://livewithai.org/ai-surveillance-human-rights-privacy/">according to LiveWithAI</a>. By using facial recognition based on race and ethnicity characteristics, the Chinese government can easily detect when a Uighur attempts to flee Xinjiang.<br><br>
Is the US Government using AI surveillance? Yes, of course. Common applications of governmental AI surveillance include military activity and security. For example <a href="https://www.theverge.com/2016/12/21/14012534/palantir-peter-thiel-trump-immigrant-extreme-vetting">Palantir might have helped to power Trump's "extreme vetting" of immigrants</a>. However, there are other applications that target improving the performance of cities.<br><br>
<a href="https://www.flickr.com/photos/23912576@N05/2962194797"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 213px; TEXT-ALIGN: center" src="//www.code-cop.org/images/JamesIThinkYourCoversBlown.jpg" alt="James, I think your cover's blown!" title="James, I think your cover's blown!" border="0" /></a><!--
--><b>Which Companies Provide These Kind of Service?</b><br>
According to the report from the Carnegie Endowment for International Peace, some of the leading companies providing AI surveillance are Huawei, ZTE and Hikvision. These companies provide AI-powered surveillance to more than 60 countries. A particularly controversial case involving AI surveillance and facial recognition technology is that of Clearview. This company collects and stores publicly available data on every person on the planet. Scraping from social media platforms such as Facebook and Instagram, Clearview has collected more than 3 billion images from social media platforms, making it the largest such library in the world. Using its enormous library of pictures, Clearview has created a search engine for faces that can be used to recognize anyone. This tool has already been used by more than 600 law enforcement agencies, including the FBI and the US Department of Justice. Clearview's willingness to do what no one else dared to do - scrape freely available data and exploit it for profit - has put it in the centre of a moral debate.<br><br>
<b>Should You Apply at Such Companies?</b><br>
Now we are getting to the meat of the discussion: As a software professional, should you work for a company that is working on this type of solution? How do you navigate the moral implications of your work? These are complex questions that seem to require deep introspection. However, at the end of the day - at least for the extreme cases mentioned above - the answer is simpler than you expect.<br><br>
On the personal level, whether working for a company like Clearview is a good idea depends on your values and what you prioritize in life. Some people abhor the whole concept of using free data to spy on people, while others would simply see nothing wrong with this idea. If you are more like the former, then working for a company like Clearview is a bad idea. It goes against your principles - you will simply not be happy in the long run, regardless of the size of that pay check. If, on the other hand, you don't see anything wrong with these practices and everything else about the job looks good, you might think it is OK to do the job. It is not.<br><br>
In his famous keynote <a href="https://www.youtube.com/watch?v=ReTi9dYuPWc">Not just code monkeys</a> Martin Fowler identified two areas where most of our impact and responsibility as a developer lie at the moment: Privacy and avoiding the creation of an alienating atmosphere at our workplaces.<br><br>
<b>Conclusion</b><br>
AI surveillance can be beneficial if used wisely and without violating privacy rights. However, there are some organizations that are using this technology to invade our privacy. The key to avoiding this is to create new policies that protect our privacy rights. As a developer, you must be aware of the implication of your work on privacy and steer clear of such violations.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com2tag:blogger.com,1999:blog-3618178407853477179.post-87332517551024522622020-09-09T12:10:00.003+02:002020-10-15T11:40:05.385+02:00Flashcards Coupling and Cohesion<a href="https://www.flickr.com/photos/70981241@N00/3979767112/"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 214px; TEXT-ALIGN: center" src="//www.code-cop.org/images/TransitionCouplingFLIRT-SBB.jpg" alt="Transition Coupling FLIRT-SBB" title="Transition Coupling FLIRT-SBB" border="0" /></a><!--
-->Low Coupling and High Cohesion are basic design principles in both functional programming and object orientation. What is coupling? <i>Coupling is the measure of the strength of association by a connection from one module to another.</i> At least that is one of the definitions I found when researching the topic. Another one is that <i>Coupling is the degree of interaction between modules.</i> Following some original research from 1974 by W. P. Stevens, G. J. Myers and L. L. Constantine, <a href="https://ieeexplore.ieee.org/document/5388187">Structured Design</a>, IBM Systems Journal Volume 13, Issue 2, Pages 115-139, there are several types of coupling and different degrees of its strength. The same is true for cohesion. These are a lot of definitions to remember - <a href="/2020/06/flashcards-and-microlearning.html">flashcards to the rescue</a>.<br><br>
<b>Flashcards</b><br>
So I created a deck of cards about coupling and cohesion. It contains 115 questions and covers<!--
--><ul><li>Definition of Coupling<!--
--></li><li>Coupling based on the type of its dependency.<!--
--></li><li>Types of coupling by strength.<!--
--></li><li>Examples of code elements with certain types of coupling.<!--
--></li><li>Postel's Law<!--
--></li><li>Coupling Contributing Factors<!--
--></li><li>Definition of Cohesion<!--
--></li><li>Cohesion based on the type of the module's elements' relationship.<!--
--></li><li>Types of cohesion by strength.<!--
--></li><li>Examples of code elements with certain types of cohesion.<!--
--></li><li>Problems caused by low strength cohesion.<!--
--></li></ul><!--
-->These are just basic definitions and code samples. Some definitions seem outdated or incomplete but I wanted to follow the original wording from Stevens, Myers and Constantine. So take them in the light of 1974. ;-) Also I am missing newer and more high level aspects of coupling and cohesion, e.g. <a href="https://connascence.io/">Connascence</a>.<br><br>
<b>Download</b><br>
I use Anki digital flashcards. Its <code>apkg</code> files can be used with <a href="https://apps.ankiweb.net/">Anki</a> for Windows, Linux, Mac and Android. For iOS there is <a href="https://www.ankiapp.com/">AnkiApp</a> but I did not confirm that it works with <code>apkg</code>. (Liviu Jianu reports that its desktop version does not work with my decks. Thank you Liviu.) Download the <a href="//www.code-cop.org/flashcards/Coupling_and_Cohesion.apkg">Coupling_and_Cohesion.apkg here</a>.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-57422642287005788492020-08-30T23:18:00.000+02:002020-08-30T23:18:39.600+02:00TDD a UI with Fast Tests<a href="https://www.flickr.com/photos/etnyk/5588953445/"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 213px; TEXT-ALIGN: center" src="//www.code-cop.org/images/Androids.jpg" alt="Androids" title="Androids" border="0" /></a><!--
-->This is another part of my series of TDD-ing user interfaces. Earlier this year I looked at test driving classic, fat, state based UIs like <a href="/2020/02/tdd-classic-state-based-ui.html">Swing or WinForms</a> and then <a href="/2020/03/tdd-vaadin-ui.html">web component libraries like Vaadin</a>. In both situations it was possible to TDD the UI using the Model View Presenter (MVP) pattern and a decent test bed for testing the implementation of the view. Later I explored <a href="/2020/03/tdd-immediate-mode-ui.html">test driving an immediate mode GUI</a>, which was even easier than doing so for retained mode: There was no need to search for components, capture events or trigger events. This time I want to experiment with test driving a user interface by only using UI tests. In theory I could do that with Swing or Vaadin, but the UI tests of these technologies are too slow. For my TDD cycle I want fast tests!
<br /><br />
<b>Android UI Tests</b><br />
My friend <a href="https://twitter.com/bastien_david">Bastien David</a> told me that Android UI tests are pretty fast and I talked him into running this experiment with me. I had never done any Android development and had only little knowledge of the Kotlin language - it is good to have friends who know. Bastien's <a href="https://github.com/SoftDevGang/login-form-tdd-ui-kata/tree/master/Android">Kotlin/​Android starting point</a> used <a href="https://developer.android.com/training/testing/espresso">Espresso</a> and <a href="http://robolectric.org/">Robolectric</a> for testing the Android UIs. The sample test<!--
--><pre class="prettyprint lang-kotlin">import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.activityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class HelloActivityTest {
@get:Rule
var activityScenarioRule = activityScenarioRule<HelloActivity>()
@Test
fun hello_activity_has_some_hello_text() {
onView(withId(R.id.text_hello)).check(matches(withText("Hello!")))
}
}</pre><!--
-->used Espresso's matchers to find the text "Hello" on the view of the <code>HelloActivity</code>.
<br /><br />
<b>First Few Tests</b><br />
We worked on the same exercise used in my previous articles, the <a href="/2020/01/login-form-tdd-ui-kata.html">Login Form exercise</a>. The first tests for UI elements of the <code>LoginActivity</code>, i.e. user name field and login button were<!--
--><pre class="prettyprint lang-kotlin">@RunWith(AndroidJUnit4::class)
class LoginActivityTest {
@get:Rule
var activityScenarioRule = activityScenarioRule<LoginActivity>()
@Test
fun `has username field with max length of 20`() {
onView(withId(R.id.username))
.check(matches(checkMaxLength(20))) // custom matcher
}
@Test
fun `has label for username`() {
onView(withId(R.id.username_label))
.check(matches(withText("Phone, email or username")))
}
@Test
fun `has login button`() {
onView(withId(R.id.login_button))
.check(matches(withText("Log in")))
.check(matches(not(isEnabled())))
}
}</pre><!--
-->These tests did not create any code, we declared the UI elements in the layout <code>app/​src/​main/​res/​layout/​activity_login.xml</code> to make each test pass. On Bastien's machine the tests were fast enough and it was easy to drive UI elements and their attributes. We had to create some custom Hamcrest matchers though, e.g. <code>checkMaxLength</code>. We decided not to go deeper and assert colours, styles or positions, but we could have.
<br /><br />
<b>Test Driving Logic</b><br />
The next test<!--
--><pre class="prettyprint lang-kotlin">
@Test
fun `when username is introduced then login button is enabled`() {
onView(withId(R.id.username))
.perform(typeText("a real username"))
onView(withId(R.id.login_button))
.check(matches(isEnabled()))
}</pre><!--
-->brought a bit of logic into the <code>LoginActivity</code>,<!--
--><pre class="prettyprint">class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
username.addTextChangedListener {
login_button.isEnabled = true // new logic
}
}
}</pre><!--
-->We only spent two hours on the exercise and did not get far. Still I could see where we would end. We would inspect every behaviour by its effect on the UI. While we could use the MVP pattern, we did not as the tests were fast enough.
<br /><br />
<b>Similar Technologies, e.g. React</b><br />
Some modern UI technologies come with a fair amount of testing support. For example the same approach should be possible with React. There is a <a href="https://github.com/SoftDevGang/login-form-tdd-ui-kata/tree/master/React">JavaScript/​React starting point in the Login Form Kata</a>. Some people have tried that. I do not know if they went far enough for a definite conclusion.
<br /><br />
David Tanzer dedicated some of his <a href="https://www.devteams.at/react_tdd/2019/11/11/react-tdd-0-all-posts.html">React TDD videos</a> on testing the UI: In <a href="https://www.devteams.at/react_tdd/2019/11/11/react-tdd-1-testing-the-ui-itself.html">Part 1: Testing the UI Itself</a> he explains the necessary setup to test React and in <a href="https://www.devteams.at/react_tdd/2019/11/18/react-tdd-2-value-and-cost-of-tests.html">Part 2: Value and Cost of Tests</a> he talks about possible test cases. He does not check text elements and style of the UI as he considers these things to have little probability of breaking later. Doing TDD, he looks for tests which influence the design of the code. I highly recommend you watch all of his videos.
<br /><br />
<b>Conclusion: Is this still TDD?</b><br />
Test driving a UI with fast tests like Android or React is certainly possible, maybe even easy. These tests are not unit tests. Is it still TDD? We definitely write the tests first so it is Acceptance test driven (A-TDD) or at least "UI specification test driven". Unlike TDD these tests do not influence the design of the code because the components of the UI are usually specified by the requirements, e.g. in wireframes. As all tests exercise the code through the UI, there is no pressure on the code, its interfaces and collaborators. Still we can evolve the code because we have full test coverage and regression safety.
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-81024118064112434852020-07-24T08:51:00.000+02:002020-07-24T08:51:02.121+02:00Interview Philipp MayerIt has been more than a year since my last <a href="/2019/01/interview-hanno-embregts.html">guest interview</a> on ethics in Software Development, and I am very happy that Philipp Mayer found the time to answer my questions. When I asked Philipp about ways to contact him, he said "I do not use any social networks for work related things :)" If you are new to the series, I am talking to people in the area of software development about our social responsibility and ethics in general. I started the <a href="/2015/10/work-with-meaning.html">series in 2015</a> as part of my own quest for work with meaning.<br />
<br />
<b>Philipp why did you choose to work with software?</b><br />
I chose to work with software in the third year of junior high school ("Unterstufe"). In maths we used the Texas Instruments Voyage 200 calculator on which one could code in TI Basic. Our teacher showed us a few things and told us we would be allowed to store any formula on there as long as we did it via writing an application for it. This motivated many of us to take a closer look at coding. This then led to choosing the IT department of the high school HTL Krems instead of becoming a chef.<br />
<br />
<b>When we met, you said that you rarely eat meat. Why do you do that?</b><br />
It does for environmental reasons. I am aware of the great impact that meat production has on climate. This has led to not buying meat unless I know it is high quality and from a source that I know. As a (working, but still) student, that means that I do not often buy meat. Nowadays when I eat meat, I see it as something special, even if it is just a pair of sausages. An exception where I do eat meat without taking care of the quality is at other people's home if it were thrown away otherwise.<br />
<br />
<b>What do you actually do regarding climate change?</b><br />
Use of public transport. I am a happy owner of the ÖsterreichCard ticket that allows me to take any train at any time within Austria. I do understand, that public transport just does not make sense for many people's everyday way to work at the moment. So I hope for improvements here. A positive thing I recently found out about is the ÖBB rail and drive service that allows me to book an electric car for less than 2 euros/hour on weekends. This is perfect for weekend trips and motivates me even more to not buy a car anytime soon.<br />
<br />
<a href="https://www.flickr.com/photos/91261194@N06/31530148188/"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 213px; TEXT-ALIGN: center" src="//www.code-cop.org/images/BalanceScale.jpg" alt="Balance Scale" title="Balance Scale" border="0" /></a><!--
--><b>Outside of climate change, what do you consider the biggest challenges of our times?</b><br />
The increasing social and financial inequality.<br />
<br />
<b>What else could we do to engage in the topic? For example, did you take part in public protests, donate money to NGOs or sign petitions?</b><!--
--><ul><li>Protests: no<!--
--></li><li>Donate money: little<!--
--></li><li>Sign petitions: some<!--
--></li></ul><!--
-->I think I make a bigger impact by living a thrifty lifestyle and trying to convince people around me to do so as well.<br />
<br />
<b>Most of these activities are personal choices. This is great but most of our time is spent on regular work. I would like to see more impact on these important topics of my regular work, just working on "the right things". Do you think that is possible?</b><br />
In general no, as the companies doing "the wrong things" tend to pay more than others. In his book <a href="https://smile.amazon.de/Die-Kunst-guten-Lebens-%C3%BCberraschende/dp/3492058736/">"Die Kunst des guten Lebens</a>, Rolf Dobelli cites the psychologist Paul Dolan saying that a sound consists of two parameters - frequency and amplitude. And that it is the same when it comes to happiness. There's the hedonistic and the eudaimonistic component. So I think that everyone has to find the right mix for oneself.<br />
<br />
<b>How do you think about selecting industry, customer and project based on your values and social responsibility?</b><br />
I would once more go with the statement made in previous answer. I think it never is a pure financial choice but about the people who you work with and to what extent one sees a meaning in the project.<br />
<br />
<b>Let's be more specific here: Would you work for an animal factory? Would you work for a sweatshop exploiting kids in Asia?</b><br />
Unfortunately, I have to be very generic with this one. For me it depends, if in my position I could enhance the situation for the poor ones (animals, children working in factories etc.) in the organization. Otherwise, I do not think I would see value in my work.<br />
<br />
<b>Did you ever reject a customer or an actual project, that would bring you money based on your values?</b><br />
No, as I did not have the chance to do so in my career, yet.<br />
<br />
<b>On the other hand, what would be industries, customers and projects that you would love to work on?</b><br />
Definitely environmental or social - in terms of improving the life of the weakest ones.<br />
<br />
<b>Thank you Philipp</b><br />
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-48328726499417522622020-06-21T22:39:00.000+02:002020-07-18T12:38:02.620+02:00Conway's Squasher CoroutineSince some time I am researching coroutines. Wikipedia says that a <a href="https://en.wikipedia.org/wiki/Coroutine">coroutine</a> is a <i>computer program component that generalises subroutines, allowing execution to be suspended and resumed. [...] Subroutines are special cases of coroutines. When subroutines are invoked, execution begins at the start, and once a subroutine exits, it is finished; an instance of a subroutine only returns once, and does not hold state between invocations. By contrast, coroutines can exit at any time, and execution may later return to these points. [...] A coroutine instance holds state, and varies between invocations.</i> Coroutines are useful for many things. For example the Kotlin programming language lists <a href="https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md#more-use-cases">several uses cases</a> including asynchronous computations, generators and implementing state machines in a sequential way. More and more languages provide them.<br />
<br />
<b>The Paper</b><br />
According to Donald Knuth, <a href="https://www.melconway.com/">Melvin E. Conway</a> coined the term coroutine in 1958 when he applied it to the construction of an assembly program. He first published it 1963 in his paper <a href="http://www.melconway.com/Home/pdf/compiler.pdf">Design of separable transition-diagram compiler</a>. Conway states that the coroutine idea was concurrently developed by him and by Joel Erdwinn. The paper is about implementing a COBOL compiler, the first two pages introduce the coroutine together with its implementation in assembly for the <a href="https://datatron.blogspot.com/2018/02/introducing-burroughs-220.html">Burroughs model 220</a>, a late vacuum-tube computer.<br />
<br />
<b>Code Example</b><br />
Conway shows an example, the asterisk squasher subroutine, in both subroutine and coroutine form. The mentioned assembly commands are unknown to me and the flowcharts are not 100% readable, so I decided to reimplement the example in modern assembly to see what is going on. <i>The asterisk squasher is a program which reads cards and writes the string of characters it finds, column 1 of card 1 to column 80 of card 1, then column 1 of card 2, and so on, with the following wrinkle: every time there are adjacent asterisks they will be paired off from the left and each "**" will be replaced by the single character "^". This operation is done with the exponentiation operator of FORTRAN and COBOL.</i><br />
<br />
<b>Asterisk Squasher Subroutine</b><br />
The problem is that <code>out</code> - the output area of the <code>SQUASHER</code> routine - only holds a single byte, which means the routine can only return and subsequentially write a single character. When looking for the second asterisk, the routine reads a second element and thus needs somehow to return it on the next call unless it was a "*". Conway continues that <i>the simple requirement of compressing asterisks requires the introduction of a switch which bifurcates the subroutine and selects the part to be used at each call depending on the situation at the last call. The reason for the switch is that each call of the subroutine must result in output of exactly one character.</i> The second read character is stored in a (module) global variable <code>t2</code> until the next call. Here is its flowchart:<br />
<!--
--><br />
<a href="http://www.melconway.com/Home/pdf/compiler.pdf"><img style="DISPLAY: block; MARGIN: 0px auto 0px; WIDTH: 472px; CURSOR: pointer; HEIGHT: 462px; TEXT-ALIGN: center" src="//www.code-cop.org/images/screens/Figure1AsteriskSquasherSubroutineWithEnvironment.jpg" alt="Figure 1: Asterisk squasher subroutine with environment" title="Figure 1: Asterisk squasher subroutine with environment" border="0" /></a><!--
--><br />
I use my <a href="/2015/07/hello-world-windows-32-assembly.html">trusted Windows assembly setup</a> for Intel IA-32 assembly. The assembly is in <a href="https://www.nasm.us/">NASM</a> format. First define the data:<!--
--><pre>card_len equ 80
switch: resd 1
%define ON dword 1
%define OFF dword 0
i: resd 1
card: resb card_len
t1: resd 1
t2: resd 1
out: resd 1</pre><!--
-->Let's warm up with the code for <code>RDCRD</code>, which reads 80 characters of a card. The code strictly follows the flowchart above.<!--
--><pre>RDCRD:
mov eax, [i]
cmp eax, card_len
jne .exit
mov [i], dword 0
<span class="com">; Omitted using Windows system library functions</span>
<span class="com">; _GetStdHandle@4 and _ReadFile@20 to read 80</span>
<span class="com">; characters into [card].</span>
.exit:
ret</pre><!--
-->The main method is <code>SQUASHER</code> with the <code>switch</code> variable.<!--
--><pre>SQUASHER:
mov eax, [switch]
cmp eax, OFF
je .off
.on:
mov eax, [t2]
mov [out], eax
mov [switch], OFF
jmp .exit
.off:
call RDCRD
mov esi, [i]
xor eax, eax
mov al, [card + esi]
mov [t1], eax
inc esi
mov [i], esi
mov eax, [t1] <span class="com">; redundant, value still in register</span>
cmp eax, <span class="str">'*'</span>
jne .not_equal_ast
.equal_ast:
call RDCRD
mov esi, [i] <span class="com">; redundant, value still in register</span>
xor eax, eax
mov al, [card + esi]
mov [t2], eax
inc esi
mov [i], esi
mov eax, [t2] <span class="com">; redundant, value still in register</span>
cmp eax, <span class="str">'*'</span>
jne .not_equal_second_ast
.equal_second_ast:
mov [t1], dword <span class="str">'^'</span>
jmp .not_equal_ast
.not_equal_second_ast:
mov [switch], ON
jmp .not_equal_ast
.not_equal_ast: <span class="com">; label 1</span>
mov eax, [t1]
mov [out], eax
.exit:
ret</pre><!--
-->There is nothing special happening in the code above. There are the two main branches <code>.on</code> and <code>.off</code>. To run the whole program on a single test card I need a <code>WRITE</code> and a main method. <code>WRITE</code> iterates a card and prints the result of each call to <code>SQUASHER</code> to standard out.<!--
--><pre>WRITE:
.loop:
call SQUASHER
<span class="com">; Omitted using Windows system library functions</span>
<span class="com">; _GetStdHandle@4 and _WriteFile@20 to write 1</span>
<span class="com">; character from [out].</span>
mov eax, [i]
cmp eax, card_len
jne .loop
ret
<span class="com">; ----------------------------------------</span>
global _main
_main:
<span class="com">; set up switch</span>
mov [switch], OFF
<span class="com">; set up global data</span>
mov [i], dword card_len
call WRITE
push 0
call _ExitProcess@4</pre><!--
--><b>Asterisk Squasher as Coroutine</b><br />
Conway writes further in his paper: <i>The coroutine approach to the same problem accomplishes the switching job implicitly by use of the subroutine calling sequence. When coroutines A and B are connected so that A sends items to B, B runs for a while until it encounters a read command, which means it needs something from A. Then control is transferred to A until it wants to "write," whereupon control is returned to B at the point where it left off.</i> In this situation A is the <code>SQUASHER</code> and B is the <code>WRITE</code> coroutine. The following flowchart shows <code>SQUASHER</code> when both it and the using program (<code>WRITE</code>) are coroutines.<br />
<!--
--><br />
<a href="http://www.melconway.com/Home/pdf/compiler.pdf"><img style="DISPLAY: block; MARGIN: 0px auto 0px; WIDTH: 314px; CURSOR: pointer; HEIGHT: 530px; TEXT-ALIGN: center" src="//www.code-cop.org/images/screens/Figure2AsteriskSquasherAsCoroutine.jpg" alt="Figure 2: Asterisk squasher as coroutine" title="Figure 2: Asterisk squasher as coroutine" border="0" /></a><!--
--><br />
<b>Coroutine in Assembly?</b><br />
While some architectures provide support for coroutines, according to the Art of Assembly Language <i>80x86 CPUs do not provide a <code>COCALL</code> instruction</i>. Conway describes the coroutine linkage on the Burroughs 220 as follows: The <code>UNCONDITIONAL BRANCH</code> instruction <code>BUN A</code> works by placing its address <code>A</code> into the P-register (the Instruction Pointer). The <code>STORE P</code> instruction <code>STP B</code> places the contents of <code>P</code> plus one into the address part of the contents of location <code>B</code>. The standard subroutine call is<!--
--><pre>1: STP EXIT <span class="com">; store 3 into target address of address EXIT</span>
2: BUN ENTRANCE <span class="com">; jump to address ENTRANCE</span>
3:</pre><!--
-->where location <code>EXIT</code> contains a <code>BUN</code> instruction whose address will be altered by the <code>STP</code> instruction in the call. (So this is self-modifying code and the return of the subroutine is then <code>EXIT: BUN 3</code> or something like that.) A pair of subroutines becomes a pair of coroutines by adding to each an isolated <code>BUN</code> instruction which we can call its router, and by changing the addresses of the <code>STP</code> and <code>BUN</code> calls as follows: when coroutine A calls coroutine B the call is<!--
--><pre> STP AROUTER
BUN BROUTER</pre><!--
-->That seems a small change for the Burroughs but how could I recreate that?<br />
<br />
<b>Coroutine in Assembly!</b><br />
The <code>BUN</code> is a <code>JMP</code> on Intel. Unfortunately not all instructions are one byte, so using the current IP + 1 as done by <code>STP</code> does not work. I tried to follow the original idea with a short macro. When coroutine A calls coroutine B the call is <code>coro A B</code>,<!--
--><pre>%macro coro 2
mov ebx, %%_cnt <span class="com">; basically IP + 1</span>
mov [route_%1], ebx <span class="com">; store it in target of router A</span>
jmp %2 <span class="com">; jump to router B</span>
%%_cnt: nop
%endmacro
route_SQUASHER: resd 1
route_WRITE: resd 1
SQUASHER:
jmp [route_SQUASHER]
WRITE:
jmp [route_WRITE]</pre><!--
-->This needs storage for the route of each coroutine. The call of the macro does not look so good as it needs the name of the current coroutine as first argument for the macro to use the right route storage. If each coroutine would be its own module, I could drop that and just use <code>[route]</code>. The router variables <code>[route_*]</code> will be initialised at startup. The code of the two routines <code>SQUASHER</code> and <code>WRITE</code> changes slightly, strictly following the second flowchart above.<!--
--><pre><span class="com">; router</span>
SQUASHER:
jmp [route_SQUASHER]
<span class="com">; coroutine</span>
SQUASHER_CORO: <span class="com">; label 1</span>
call RDCRD
mov esi, [i]
xor eax, eax
mov al, [card + esi]
mov [t1], eax
inc esi
mov [i], esi
mov eax, [t1] <span class="com">; redundant, value still in register</span>
cmp eax, <span class="str">'*'</span>
jne .not_equal_ast
.equal_ast:
call RDCRD
mov esi, [i] <span class="com">; redundant, value still in register</span>
xor eax, eax
mov al, [card + esi]
mov [t2], eax
inc esi
mov [i], esi
mov eax, [t2] <span class="com">; redundant, value still in register</span>
cmp eax, <span class="str">'*'</span>
jne .not_equal_second_ast
.equal_second_ast:
mov [t1], dword <span class="str">'^'</span>
jmp .not_equal_ast
.not_equal_second_ast:
mov eax, [t1]
mov [out], eax
coro SQUASHER, WRITE
mov eax, [t2]
mov [out], eax
coro SQUASHER, WRITE
jmp SQUASHER_CORO
.not_equal_ast: <span class="com">; label 2</span>
mov eax, [t1]
mov [out], eax
coro SQUASHER, WRITE
jmp SQUASHER_CORO
<span class="com">; ----------------------------------------</span>
<span class="com">; router</span>
WRITE:
jmp [route_WRITE]
<span class="com">; coroutine</span>
WRITE_CORO:
.loop:
coro WRITE, SQUASHER
<span class="com">; Omitted using Windows system library functions</span>
<span class="com">; _GetStdHandle@4 and _WriteFile@20 to write 1</span>
<span class="com">; character from [out].</span>
mov eax, [i]
cmp eax, card_len
jne .loop
ret
<span class="com">; ----------------------------------------</span>
global _main
_main:
<span class="com">; set up coroutine routers</span>
mov ebx, SQUASHER_CORO
mov [route_SQUASHER], ebx
mov ebx, WRITE_CORO
mov [route_WRITE], ebx
<span class="com">; set up global data</span>
mov [i], dword card_len
call WRITE
push 0
call _ExitProcess@4
</pre><!--
--><b>Conslusion</b><br />
I hope that clarifies how the first coroutine presented in 1963 worked. Re-coding the example was a lot of work and in the end it paid off because everything is clear now, even more so after I wrote this blog post about it. This is the golden triangle of learning: <a href="/2014/04/how-to-divide-learning-time.html">theory (e.g. reading about it), practice (e.g. creating it) and finally teaching (documenting and sharing it)</a>.<br />
<br />
<b>Full Source Code</b><br />
After I published this article <a href="https://twitter.com/dmitrykandalov">Dmitry Kandalov</a> pushed me to make the <a href="https://github.com/codecop/Conways-Squasher-Coroutine">code available on GitHub</a>. And then we went to port it to macOS, so he could play with it as well. To compile and run the code you need GNU make, <a href="https://www.nasm.us/">NASM</a> and a linker depending to your platform. Thanks to Samir Talwar's <a href="https://github.com/SamirTalwar/smoke">Smoke</a>, it even comes with tests. Give it a try: <a href="https://github.com/codecop/Conways-Squasher-Coroutine">Conway's Squasher Coroutine @ GitHub</a>.<br />
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com2tag:blogger.com,1999:blog-3618178407853477179.post-36374244763609178732020-06-12T16:40:00.000+02:002020-06-12T16:43:36.774+02:00A New DogLast year our <a href="/2019/08/in-memory-of-ruby.html">dog Ruby died</a>. We took some time to cope with the loss and now is the time for a new dog. After we loved a Great Dane once, there is no other dog we want. Here is a picture of our new puppy Ronja:<br />
<!--
--><br />
<img style="DISPLAY: block; MARGIN: 0px auto 0px; WIDTH: 500px; HEIGHT: 375px; TEXT-ALIGN: center" src="//www.code-cop.org/images/photos/Ronja.jpg" alt="Great Dane puppy Ronja" title="Great Dane puppy Ronja" border="0" /><!--
--><br />
While I chose the name of our previous dog - Ruby - my wife chose the name of this one. Ronja or <a href="https://en.wikipedia.org/wiki/Ronia,_the_Robber%27s_Daughter">Ronia</a> is the daughter of the leader of a clan of robbers. Obviously she has little manners and does what she likes - and that is exactly the nature of our little Ronja ;-)<br />
<br />
<b>Raising a Puppy</b><br />
Like software development, raising a puppy is a detailed process which can be improved continuously. Today we know more than ten years ago and we want to do much better. There are many misconceptions how to raise dogs and I learnt again that knowing how to handle certain situations is not enough - I have to practice them. For example, grabbing the puppy on time so it will not pee on the carpet is a skill. If you ever plan to raise a puppy I recommend to check out the books by Ian Dunbar, <a href="https://www.amazon.com/Before-You-Get-Your-Puppy-ebook/dp/B005F7IPL4/">BEFORE You Get Your Puppy</a> and <a href="https://www.amazon.com/After-You-Get-Your-Puppy-ebook/dp/B005F9UWZO/">AFTER You Get Your Puppy</a>. These are small books, fun and easy to read. Both books are provided as e-books courtesy of <a href="https://www.simpawtico-training.com/">simpawtico dog training</a> in the downloads section. And even if you do not own any dogs, reading these books will help you understand why dogs behave how they do - especially if they have been trained badly.<br />
<br />
<a href="https://www.simpawtico-training.com/learning/downloadables/"><img style="WIDTH: 194px; CURSOR: pointer; HEIGHT: 300px; TEXT-ALIGN: center" src="//www.code-cop.org/images/books/book_BEFORE_You_Get_Your_Puppy.jpg" alt="BEFORE You Get Your Puppy book cover" title="BEFORE You Get Your Puppy book cover" border="0" /> <img style="WIDTH: 194px; CURSOR: pointer; HEIGHT: 300px; TEXT-ALIGN: center" src="//www.code-cop.org/images/books/book_AFTER_You_Get_Your_Puppy.jpg" alt="AFTER You Get Your Puppy book cover" title="AFTER You Get Your Puppy book cover" border="0" /></a><br />
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-35432269531981828142020-06-04T17:36:00.003+02:002020-09-10T00:01:42.190+02:00Flashcards and MicrolearningI like <a href="/2014/04/how-to-divide-learning-time.html">learning in all its aspects</a>. A large part of software work is hands-on, so I experiment a lot and work through old and <a href="/2019/11/promotion-service-kata.html">new code katas</a> alike. For theory I rely on classic books like <a href="/2012/02/required-reading-clean-code.html">Clean Code</a>. Sometimes I struggle to internalise theoretical knowledge and take notes, create extracts, mind maps or sketch notes. For material I need to memorise I like (digital) flashcards.<br />
<br />
<b>Applications of Flashcards</b><br />
I use flashcards for a lot of different things.<!--
--><ul><li>The common case is to study tiny facts like words or numbers. <a href="/2016/01/ide-shortcut-flashcards.html">IDE shortcuts</a> and <a href="/2019/03/flashcard-madness-learning-to-spell.html">spelling alphabets</a> are in this category. These flashcards work very well for me.<!--
--></li><li>Then I tried <a href="/2016/07/improving-typing-accuracy.html">visualising keys</a>, which did not work as well.<!--
--></li><li>I also use them to remember key points from books, e.g. <a href="/2019/02/flashcard-madness-little-schemer.html">The Little Schemer</a> or <!-- TODO link future post: secrets of consulting flashcards -->Gerald M. Weinberg's Secrets of Consulting. Key learnings from books, i.e. phrases or sentences, are more difficult to remember. I am still experimenting with these - maybe flashcards are not ideal here.<!--
--></li><li>In the past I created decks of cards to accompany some of my training workshops, e.g. <!-- TODO link future post: design patterns flashcards -->Design Patterns. While participants were enthusiastic about them, I am pretty sure they did not use them to deepen their newfound knowledge. People use different phones, so the availability of flashcard apps is also an issue.<!--
--></li><li>Even when I fail to study the cards later, creating them is a learning experience on its own. I have to collect and structure the material, formulate the questions and find precise answers. For example I created cards around <a href="/2020/09/flashcards-coupling-and-cohesion.html">Coupling and Cohesion</a> which helped me understand more of these two concepts.<!--
--></li></ul><!--
--><a href="https://www.flickr.com/photos/pontla/27601985028/"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 188px; TEXT-ALIGN: center" src="//www.code-cop.org/images/microGarden.jpg" alt="Micro Garden" title="Micro Garden" border="0" /></a><!--
--><b>Microlearning</b><br />
By researching flashcards, I came across Microlearning. This is kind of a buzz word - everything is micro today, e.g. Micro-Workouts. (You practice for five minutes a day and then the exercise gear folds under your bed ;-) Wikipedia says that <a href="https://en.wikipedia.org/wiki/Microlearning">Microlearning</a> <i>deals with relatively small learning units and short-term learning activities. [...] In a wide sense, Microlearning can be understood as a metaphor which refers to micro aspects of a variety of learning models, concepts and processes.</i> It is a new concept and there is no clear definition. It contains a lot of things. Besides the obvious reading, listening or watching short pieces of information, Microlearning activities include flashcards, quizzes, answering multiple-choice questions, micro games and more.<br />
<br />
<b>Conclusion</b><br />
I was surprised to learn that sorting and organising learning content like tagging it (e.g. <a href="https://en.wikipedia.org/wiki/Social_bookmarking">Social Bookmarking</a>) is considered Microlearning. I like sorting and connecting information, I even <a href="/2015/05/how-to-organise-your-code-katas.html">sort my code katas</a>. The most fun activity listed on Wikipedia is <i>composing a haiku or a short poem</i>. I did <a href="/2009/10/coders-dread.html">compose a poem in the past</a> but never considered it a tool for learning. I like the idea. Maybe I will write a <!-- TODO link future post: learning poem -->poem about TDD or Micro Services in the future.<br />
<br />
I do not consider a whole deck of flashcards Microlearning. A whole deck is so much more as it contains all the aspects and details about a certain topic. In addition, creating it takes several hours. I am seeing that because I create most of my decks myself. Probably I am putting too much information into them as well. Sometimes I am overwhelmed by my own questions. For example my <!-- TODO link future post: design patterns flashcards -->Design Patterns deck contains more than 360 questions including class diagrams and all. On the other hand, learning a few cards now and then - especially from an unknown deck - is fine.<br />
<br />
Listening and watching short audio or video recordings is Microlearning, too. I like to listen to podcasts, especially if each episode is focused and not too long. That means it is shorter than ten minutes. Short episodes are easy to consume between other activities, e.g. when commuting. It is easier to stay focused. (Yes, maybe I am <!-- TODO link future post: getting older, harder to focus -->getting old. I have less time and energy for prolonged learning.) That is the reason I plan for episodes of eight minutes in my own <a href="https://coderetreat-facilitation.code-cop.org/">podcast on Coderetreat Facilitation</a>. Short episodes are easier to produce, which allows me to publish more often.<br />
<br />
<b>Bonus Material</b><br />
The <a href="https://de.wikipedia.org/wiki/Mikrolernen">German Wikipedia entry on Microlearning</a> contains a paragraph on Microlearning in the context of software development. It lists Test Driven Development as an example. This is an interesting angle. When the test - an assumption - goes green, the implementation moved forward a micro step and the developer knows a tiny bit more about the system.<br />
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0tag:blogger.com,1999:blog-3618178407853477179.post-56853756652226888642020-05-06T11:07:00.002+02:002023-10-19T13:19:39.466+02:00Learning yet another Programming LanguageIn 2000 Andrew Hunt and David Thomas wrote their influential book <a href="https://pragprog.com/book/tpp20/the-pragmatic-programmer-20th-anniversary-edition">The Pragmatic Programmer</a>, which is listed as second <a href="https://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read">single most influential book every programmer should read</a>. (I listed it in my book recommendations both <a href="/2012/01/literature-for-java-developers.html">2012</a> and <a href="/2006/08/java-bookshelf.html">2006</a>.) Chapter one, tip eight <i>Invest Regularly in Your Knowledge Portfolio</i> says: <i>Learn at least one new language every year. Different languages solve the same problems in different ways. By learning several different approaches, you can help broaden your thinking and avoid getting stuck in a rut.</i><br /><br />
<a href="https://www.flickr.com/photos/kefraya/4805097392/"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 297px; TEXT-ALIGN: center" src="//www.code-cop.org/images/Werkzeugkasten.jpg" alt="Filled Tool Box (licensed CC BY-NC by hmboo Electrician and Adventurer)" title="Filled Tool Box (licensed CC BY-NC by hmboo Electrician and Adventurer)" border="0" /></a><!--
-->I started out as <a href="/2006/01/my-cup-of-java.html">Java developer</a>. Since than I have studied XSLT, Ruby, <a href="/2009/03/start-scala.html">Scala</a>, Forth, JavaScript, <a href="/2018/12/scheme-programming-language.html">Scheme</a>, Python, TypeScript, Go, C# and C. Out of these I even ran trainings for developers teaching them Python and TypeScript. In addition I had a glimpse of Visual Basic, Dart, Clojure, R, PHP, NATURAL, PowerShell, Kotlin and have relearned Assembly. I still need to learn Smalltalk, F#, maybe Haskell, J and of course Prolog.<br /><br />
I like programming languages and my learning approach is driven by curiosity and fun. Today I will describe my "standard", step by step way to get into a new language. <span style="color:red">I will assume you are an experienced developer, able to code in Java or C# who understands basic programming principles.</span> I believe this approach is not suitable for programming newbies. I never use all these steps and sometimes change their order - like starting with the last one. Feel free to reorder or skip any steps not adding knowledge or fun.<br /><br />
<b>1) Get an overview of core language features.</b><br />
I start reading Wikipedia about the programming language I want to dive into. I am looking for the core features, used concepts and paradigms in the language. Code examples of these features provide a first idea of the language's syntax. The idea is not to know everything, just to be able to write some code. Writing code is the fun part, not reading. The more languages you know the easier and faster this step is. When learning Go one hour on Wikipedia during commute was enough. On the other hand for TypeScript I spent several hours reading the language reference (Handbook). For C# I skipped this step as I had seen most of the language features while facilitating <a href="/2014/09/teaching-using-mob-programming.html">Mob Programming sessions</a>.<!--
* TS 6h
* Go 1h
* C# skipped
--> You are done with this step when you have some idea what the language can do.<br /><br />
<b>2) Figure out the usual setup and get it working.</b><br />
Most programming languages come with their own ecosystem of runtimes, documentation, dependency and packaging mechanisms, testing frameworks, editors and other tools. When starting with a new language I try to use its typical tooling. Or at least I look for a decent IDE plugin to keep some level of comfort and productivity. Often this is painful and full of compromise. E.g. when working with Scheme I should have used Emacs but started with a <a href="/2019/01/scheme-runtime-and-editor-choices.html">basic editor and used VS Code in the end</a>. For Go I needed 2 to 3 hours to set up the command line tools and VS Code integration. For C it took me 2 hours to compile and run a sample test alone - due to incompatible architecture binaries, sigh. I am still staying away from make tools due to the additional complexity. Eventually I will have to work through them if I want to use high level IDEs like Eclipse or CLion. If your interest in the language is purely educational, a simple editor might be enough to get started, like I used for <a href="/2011/02/ultraedit-and-gforth.html">Forth</a>.<!--
* Go 3h
* C99 2h
--> You are done when you are able to edit, compile, test and run a Hello World application, e.g. <a href="/2015/07/hello-world-windows-32-assembly.html">in Windows Assembly</a>.<br /><br />
<b>3) Port small pieces of code (from a similar language if possible).</b><br />
This helped me when learning C. I knew its basic features and had figured out how to compile and run a single file. And then I ported some small (refactoring) code katas. Porting code katas was easier than coding them because the solution and its code were already there and all I needed to deal with was syntax. If there is a similar language to start from, e.g. Java to C#, Java to PHP, C++ to C, even Java to C, then some of the syntax is proper right from the start. There was a lot of Google and StackOverflow involved and I managed to convert a small kata in around one hour. In the end I had ported several code katas to C. <a href="https://github.com/emilybache">Emily Bache</a> keeps inventing fun and interesting refactoring katas, which always need ports to other languages. For example I have ported her <a href="https://github.com/emilybache/Parrot-Refactoring-Kata">Parrot-Refactoring-Kata</a> to TypeScript, Go and recently C. I have also contributed a Scheme version, but that was after I had learnt the language.<!--
* TS 1 Katas
* Go 2 Katas
* C# 1 Kata (promotion-service-kata)
* C99 3h = 5 Katas (Electric Rose, Parrot*2, Device Driver*2)
--> You are done when you have contributed at least two ports of small refactoring katas.<br /><br />
<b>4) Work through koans of the language.</b><br />
Koans are an effective way to <a href="https://www.lauradhamilton.com/learn-a-new-programming-language-today-with-koans">learn new programming languages</a>. Programming language koans are a progressive sequence of little exercises, starting with basic things and building on each other to move to more advanced topics. The goal is to learn the language and core libraries. Usually the exercises contain failing test cases, where tiny pieces of code have to be filled in to make them pass. (I have used this idea to teach unit testing in <a href="/2015/12/testing-koans.html">Java and PHP</a> as well as <a href="/2018/06/xunit-testing-koans-reloaded.html">Python and C#</a>. Porting the koans from JUnit to xUnit also helped me to get into C# - see the paragraph on porting small pieces of code.) Koans are awesome and I use them regularly. I worked through some <a href="https://github.com/gregmalcolm/python_koans/wiki">Python koans</a>, two third of <a href="https://github.com/Kotlin/kotlin-koans">Kotlin koans</a> and all <a href="https://github.com/c-koans/c_koans">C Koans</a>. The koans vary in size. While Kotlin contained 6 lessons, Python had 39 and <a href="https://jskatas.org/">JavaScript</a> even 78. Working all these 78 exercises took me more than<!-- TODO link future post: Learning workshop Goerge --> three full work days in total.<!--
* Python 10 of 39
* Kotlin 4 of 6
* TS all 78
* C99 all 13
--> You are done when you have completed (almost) all of the koans for the new language.<br /><br />
<b>Ninety-Nine Problems</b><br />
In case there are no koans for your language, look for "Ninety-Nine Problems". The idea is based on Werner Hett's <a href="https://sites.google.com/site/prologsite/prolog-problems">P-99: Ninety-Nine Prolog Problems</a>. These are little problems with different levels of difficulty. Sample solutions are available in Java, Scala, Haskell, <a href="https://github.com/dkandalov/kotlin-99">Kotlin</a>, F#, OCaml and probably others.<br /><br />
<a href="https://www.flickr.com/photos/cute-is-what-i-aim-for/3095728542/"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 213px; TEXT-ALIGN: center" src="//www.code-cop.org/images/scratches.jpg" alt="scratches - What is the connection between this image and item 6? (licensed CC BY-NC-ND by Sue)" title="scratches - What is the connection between this image and item 6? (licensed CC BY-NC-ND by Sue)" border="0" /></a><!--
--><b>5) Watch some recorded talks and online presentations.</b><br />
This is the most obvious step. I like to watch recorded presentations, during my commute. Sometimes some extra (passive) information helps me understand a language, or even this specific weird feature. Depending on time and interest this can be a few talks, or whole months of commute.<!--
* TS 6h
* Go 2h
* C# 0h
* C 0h
--><br /><br />
<b>6) TDD some code katas from scratch.</b><br />
Now is the time to write some code from scratch. I recommend starting with simple exercises. There is no point in getting frustrated right at the start. <a href="/2017/10/difficulty-of-coding-exercises.html">Manage the difficulty of your exercises</a>: Use simple katas like FizzBuzz, Prime Factors, Roman Numerals or Word Wrap to get started. For example I used <a href="/2013/05/xsltunit-ant-support.html">FizzBuzz to practice some XSLT</a> and Prime Factors when revisiting old languages I used to know many years ago - like <a href="/2010/01/prime-factors-kata-basic.html">BASIC</a>. I reuse these katas - and know their solutions - I just want to try them in a new language. Later I move to more complicated assignments like Bowling, Minesweeper (<a href="/2015/07/minesweeper-near-metal.html">when I revisited Assembly after 20 years</a>), Bank OCR (<a href="/2015/11/bank-ocr-kata-in-scheme.html">when I studied Scheme</a>) or Conway's Game of Life.<!--
* TS 1 kata = 4h
* Go 3 katas
* C# 1 katas
* C 4-5 katas
--> You are done when you have implemented a few code katas from scratch including tests.<br /><br />
<b>7) Write more code, e.g. tackle a larger code base.</b><br />
There is no other way of getting deeper into a programming language than using it. This calls for a larger side project. It can be a complex code kata, a little video game like Pong or Tron (<a href="https://en.wikipedia.org/wiki/Nibbles_(video_game)">Nibbles</a>) - including graphics of course - or whatever comes to your mind. As I am fond of Scheme, I have build several Scheme interpreters in new languages. You could even <a href="https://martinfowler.com/bliki/Xunit.html">implement your own unit testing framework</a>, which is also recommended by Kent Beck as an exercise to get into a new language. (And I did that for <a href="/2010/02/turbo-pascal-prime-factors-kata.html">Pascal</a>, <a href="/2015/08/how-to-unit-test-assembly.html">Assembly</a> and <a href="/2023/10/unit-testing-scheme.html">Scheme</a>.)<!--
* Scheme C64 Parser 110h
* C# Snake 3D 15h
* Go Lisp 13h
* C Product Export 16+h
--> Depending on the time invested into the previous steps, a side project includes more or less trial and error. If there is too much hassle, I stop and go back to previous steps to learn more about the basics. There is no point in being stuck. For example when studying Go, I went for the side project after 3 hours of researching the language, which was too early. So I spent some more time on theory and then continued working on my idea. My usual learning side projects take around 15 to 20 hours - or that is the time when I lose interest. You are done when you have worked on a larger code base for at least 15 to 20 hours.<br /><br />
<b>8) At last get *all* the details.</b><br />
Now that I am familiar with the basics of the language and its ecosystem, it is time to dive deeper. After some month of experimenting and hands-on practice - steps 2, 3, 4, 6 and 7 all involve writing code - I am drawn back to theory. I like to <a href="/2014/04/how-to-divide-learning-time.html">balance my learning between theory, experiments and practice</a>. To conclude learning a new language I might study a classic book about that language. It should cover the language and its features completely and I read it from cover to cover. At that time I am already familiar with many parts of the language, reading progress is fast. I am interested in the all the details, the bits and pieces I did not encounter during my experiments. Language specifications are usually dry and perfectly suited for this step as well as classic titles like the "Pickaxe book", K&R and SICP (although SICP is so much more than a Scheme book...)<!--
* Java "Thinking in Java", JLS
* Ruby "Pickaxe book"
* Scala "Programming in Scala"
* Regex "Mastering Regular Expressions"
* Scheme "SICP"
* C "K&R"
--> You are done when you read a classic book on the new language from cover to cover.<br /><br />
<b>Conclusion</b><br />
I like programming languages and learning new ones is adventurous and fun. I try to learn a new language every year. Not all learning goes deep. Not all languages stick. Unless you are working on real projects in all of these languages at the same time, it is natural to forget some details. And that is perfectly fine. It is all about incorporating new paradigms and widening your perspective. So keep learning!
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com1tag:blogger.com,1999:blog-3618178407853477179.post-83461415604025990582020-03-27T17:58:00.001+01:002020-03-27T17:58:48.385+01:00TDD an Immediate Mode UIToday I continue my experiments with test driving user interfaces. First I looked at test driving classic, fat, state based UIs like <a href="/2020/02/tdd-classic-state-based-ui.html">Swing or WinForms</a> and later <a href="/2020/03/tdd-vaadin-ui.html">web component libraries like Vaadin</a>. I need to explore different programming environments and platforms to see what is possible. In this post I want to have a look at <a href="https://en.wikipedia.org/wiki/Immediate_mode_GUI">immediate mode GUIs</a>. An immediate mode GUI is a GUI where the event processing is directly controlled by the application. When I first read a similar sentence on Wikipedia, it did not help me at all. So what is an immediate mode GUI?<br />
<br />
<a href="https://www.flickr.com/photos/pierrepita/9459601342/"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 213px; TEXT-ALIGN: center" src="//www.code-cop.org/images/UserInterface.jpg" alt="User Interface" title="User Interface" border="0" /></a><!--
--><b>Retained Mode</b><br />
A better question would be "what is <a href="https://en.wikipedia.org/wiki/Retained_mode">retained mode</a>?" Wikipedia states that <i>retained mode is a style of API design in which the graphics library retains the complete object model of the rendering primitives to be rendered.</i> That means that the widget, e.g. an instance of a <code>JButton</code>, contains all state needed to draw the button, i.e. colours, position, is the button clicked and so forth. When the button is created, or even "drawn", it is not causing the actual rendering. The GUI library decides when and how to render the widget and optimises the actual rendering. This includes double buffering, clipping or partial updates. Retained mode is the dominant style in GUI libraries, all user interfaces you have build were likely of this style.<br />
<br />
<b>Immediate Mode</b><br />
So let's get back to <a href="https://en.wikipedia.org/wiki/Immediate_mode_(computer_graphics)">Immediate mode</a>. When using an immediate mode GUI library, the event processing is directly controlled by the application. There is no button object, there is just a <code>Button(bounds Rectangle, text string)</code> function which immediately draws the button with given text at the given position and size (argument <code>bounds</code>). The function returns <code>true</code> if the button was clicked. The application code must call all drawing commands required to describe the entire scene each time a new frame is displayed. This is often used in video games programming and examples of immediate mode rendering systems include Direct2D and OpenGL. If you want to know more about this mode, see this <a href="https://stackoverflow.com/questions/51662877/are-there-any-basic-immediate-mode-gui-tutorials">list of immediate mode gui tutorials</a> on StackOverflow.<br />
<br />
The (immediate mode) UI framework I am going to use is <a href="http://www.raylib.com/">raylib</a>, <i>a simple and easy to use library to enjoy video games programming</i>. See <a href="https://www.raylib.com/cheatsheet/cheatsheet.html">its cheat sheet</a> for an overview of its functions. It has a simple API which hides everything regarding windowing system and environment. I am writing code in <a href="https://golang.org/">Go</a>, so I am using <a href="https://github.com/gen2brain/raylib-go">raylib-go</a>, the Golang bindings for raylib. Honestly I have no idea what I am doing. I have never used an immediate mode framework, not even heard of one before last year. In addition I know little to nothing about the Go language. Nevertheless I managed to talk my fellow crafter, Extreme Programmer and probably Vienna's longest time Go practitioner, <a href="https://twitter.com/dertseha">Christian Haas</a> into running this experiment with me. We spent one full day working on the <a href="/2020/01/login-form-tdd-ui-kata.html">Login Form exercise</a>.<br />
<br />
<b>The first test: There is a button</b><!--
--><pre class="prettyprint lang-go">import (
"testing"
...
rl "github.com/gen2brain/raylib-go/raylib"
)
func TestForm_LoginButton(t *testing.T) {
var form login.Form
ui := newTestingUI()
form.Render(ui)
if !ui.buttonCalled {
t.Errorf("Button() was not called")
}
}</pre><!--
--><code>Form</code> is the <code>struct</code> containing the form's data, which is empty for now. <code>Render</code> is a receiver function on the form, which creates a button with no bounds and an empty text.<!--
--><pre class="prettyprint lang-go">type Form struct{}
func (form Form) Render(ui FormUI) {
ui.Button(rl.Rectangle{}, "")
}</pre><!--
-->To check that certain calls into raylib have been made, there is an interface <code>FormUI</code> between the application code and raylib. In the tests this interface is mocked to verify certain calls have been made. (In Go an <a href="https://tour.golang.org/methods/9">interface</a> type is defined as a set of method signatures. This is the <a href="https://golangbot.com/polymorphism/">way to achieve polymorphism</a>.)<!--
--><pre class="prettyprint lang-go">type testingUI struct {
buttonCalled bool
}
func (ui *testingUI) Button(bounds rl.Rectangle, text string) bool {
ui.buttonCalled = true
return false
}</pre><!--
-->This follows an approach I have found as a possible TDD approach:<!--
--><ul><li>Design and write your methods separated from the actual UI.<!--
--></li><li>TDD the elements and behaviour.<!--
--></li><li>Mock single UI elements to verify necessary calls but do not show them.<!--
--></li></ul><!--
-->For <a href="/2020/02/tdd-classic-state-based-ui.html">Swing</a> I cannot see how this approach would be practical, but in this example with immediate mode raylib, it feels natural.<br />
<br />
<b>More Code</b><br />
Soon the number of interactions with the UI made it necessary to add string ids to each drawing primitive. While raylib did not need them, other libaries do, so it did not feel wrong to add them. The mocked UI was growing. Here are the final pieces of code for the login button.<!--
--><pre class="prettyprint lang-go">type testingUI struct {
// verify if Button method has been called (mock)
buttonCalled map[string]bool
// record button's text and bounds for later inspection (spy)
buttonText map[string]string
buttonBounds map[string]rl.Rectangle
// return value of the Button method = user interaction (stub)
buttonResults map[string]bool
...
}
func newTestingUI() *testingUI {
ui := &testingUI{
buttonCalled: make(map[string]bool),
buttonText: make(map[string]string),
buttonBounds: make(map[string]rl.Rectangle),
buttonResults: make(map[string]bool),
...
}
return ui
}
func (ui *testingUI) Button(id string, bounds rl.Rectangle, text string) bool {
ui.buttonCalled[id] = true
ui.buttonText[id] = text
ui.buttonBounds[id] = bounds
result := ui.buttonResults[id]
ui.buttonResults[id] = false // reset button click after first call
return result
}
func TestForm_LoginButton(t *testing.T) {
var form login.Form
ui := newTestingUI()
form.Render(ui)
if !ui.buttonCalled["login"] {
t.Errorf("not found")
}
}
func TestForm_LoginButtonText(t *testing.T) {
var form login.Form
ui := newTestingUI()
form.Render(ui)
if "Log in" != ui.buttonText["login"] {
t.Errorf("is not \"Log in\"")
}
}
func TestForm_LoginButtonBounds(t *testing.T) {
var form login.Form
ui := newTestingUI()
form.Render(ui)
expectedBounds := rl.Rectangle{300, 165, 110, 30}
if ui.buttonBounds["login"] != expectedBounds {
t.Errorf("expected %v, but was %v", expectedBounds, ui.buttonBounds)
}
}</pre><!--
-->and the production code<!--
--><pre class="prettyprint lang-go">type FormUI interface {
Button(id string, bounds rl.Rectangle, text string) bool
...
}
func (form *Form) Render(ui FormUI) bool {
buttonBounds := rl.Rectangle{X: 300, Y: 165, Width: 110, Height: 30}
if ui.Button("login", buttonBounds, "Log in") {
// TODO authenticate
}
return false
}</pre><!--
-->The third test, <code>TestForm_LoginButtonBounds</code> checks the position and size of the button. These properties are considered "layout". I do not like to test layout. I had to open GIMP to decide on the proper rectangle in <code>expectedBounds</code>, which I really dislike. I also expect this values to change a lot during initial development. Additionally <code>Rectangle</code> is a raylib type and so we depend on raylib in our code. Other options would have been:<!--
--><ul><li>Ignore layout completely. But then we would need to revisit all calls and add the <code>Rectangle</code>s later.<!--
--></li><li>Use abstract coordinates, i.e. map my coordinates into raylib <code>Rectangle</code>s. That seemed like an extra overhead.<!--
--></li><li>Move the responsibility of layout into the wrapper. There would be a button method for each button in the application and there would be more code outside my tests.<!--
--></li><li>Move out the bounds and store them in the wrapper with a simple lookup on the id. Moving out stuff is against the nature of Immediate mode because the whole UI is expected to be in the code.<!--
--></li></ul><!--
-->The wrapper for raylib is straight forward.<!--
--><pre class="prettyprint lang-go">type RaylibFormUI struct{}
func (ui *RaylibFormUI) Button(id string, bounds rl.Rectangle, text string) bool {
return raygui.Button(bounds, text)
}</pre><!--
-->This should give you an idea how things worked out. If you want to follow our TDD steps, <a href="https://github.com/SoftDevGang/login-form-tdd-ui-kata/commits/try-go">here are the individual commits</a>.<br />
<br />
<b>Is this MVP?</b><br />
The MVP (Model View Presenter pattern) has a very thin, dumb UI, which is called the view. The model contains the UI data or UI model which might contain information about enabled fields, active buttons and so on. The presenter is a mediator and wires the model and the view. In the Go code above, the <code>Form</code> structure could be seen as an UI model. Later it will hold the user name and password data. The form receiver function <code>func (form *Form) Render(ui FormUI) bool</code> contains the presenter logic. It is not a separate object - there are no objects in Go - but it could be separate. Due to the immediate mode UI, there are no callbacks from the view in case of events. This removes the need for the usual MVP event listeners. The <code>FormUI</code> interface is like a MVP view as it hides the raylib dependency. It does not abstract away the underlying library, it is just a thin wrapper. It is not a MVP view. It could be made a view, i.e. provide more abstract functions in domain language, and then it would need tests on its own. In the experiment, this seemed unnecessary. In the end the <code>FormUI</code> will delegate many functions to raylib, so it could be generated from its original source code. This shows the tight coupling of the <code>FormUI</code> and the underlying UI library.<br />
<br />
<a href="https://www.flickr.com/photos/archeon/4114465790/"><img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; WIDTH: 320px; CURSOR: pointer; HEIGHT: 213px; TEXT-ALIGN: center" src="//www.code-cop.org/images/WaterPressure.jpg" alt="Water Pressure" title="Water Pressure" border="0" /></a><!--
--><b>Conclusion</b><br />
We built a login user interface following the requirements using Test Driven Development. It was easy and we did not face any problems, so no big deal. The Immediate mode library made it easier than for retained mode: There was no need to search for components, capture events, trigger events and so forth, definitely easier than <a href="/2020/02/tdd-classic-state-based-ui.html">my initial experiment</a>. When comparing these experiments for Swing and raylib, I am reminded of the difference of Classic and Mockist TDD. In retained mode, e.g. Swing, I kept checking the state of UI components while in immediate mode I verified expected calls of the library. This approach allows variable depth of checks. We could have asserted colours and styles and we did not. So we will have to look at the finished form in the end. Christian proposed saving the image of the final view and storing it for regression testing.<br />
<br />
We used TDD but there was little pressure on the design of the code. There was some pressure on the design of the API of <code>Form</code>, but there was no pressure on its internal workings nor on <code>FormUI</code> at all. The tests drove the creation of the UI - which was dictated by the requirements - there was no space for evolution. A different (UI) design might have been easier to test, but that was not an option. (A different UI would not have been different to test in this example anyway.) So we lost this particular benefit of TDD.<br />
<br />
<b>Try it yourself</b><br />
I will continue my experiments and I would like to hear your ideas on the topic. The Go starting code with raylib-Go, its required dependencies and linter setup is available in the <a href="https://github.com/SoftDevGang/login-form-tdd-ui-kata">Login Form Kata</a>. Try it yourself!<br />
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com1tag:blogger.com,1999:blog-3618178407853477179.post-23876976927933124482020-03-04T22:12:00.002+01:002020-04-24T23:57:46.442+02:00TDD a Vaadin UIAs <!-- TODO link future post: job as Code Cop -->Code Cop I am working to get teams into adopting TDD. I use a mixture of classic training, guided workshops, Coding Dojos, <a href="/2015/07/external-code-reviews.html">code reviews</a> and <a href="/2018/07/three-rules-of-coaching-engagement.html">coaching</a> to make this happen. One of my clients is working with Vaadin and keeps using it as an <a href="/2019/08/y-u-no-tdd.html">excuse to not use TDD</a>. Not good. After my recent <a href="/2020/02/tdd-classic-state-based-ui.html">experiments with test driving user interfaces</a> I "hijacked" one of our <a href="/2014/09/teaching-using-mob-programming.html">mob programming</a> sessions and we worked on the <a href="/2020/01/login-form-tdd-ui-kata.html">Login Form Kata</a>.<br />
<br />
<b>Vaadin</b><br />
The client uses <a href="https://vaadin.com/vaadin-8">Vaadin 8</a> and the web has several ideas how to test (drive) it:<!--
--><ul><li>Use the Model View Presenter pattern, see <a href="https://vaadin.com/docs/v8/framework/advanced/advanced-architecture.html">Vaadin Advanced Application Architectures</a>.<!--
--></li><li>Gradually separate the UI from the logic, thinking of MVP more as a process than a pattern, starting with separate methods, which are accessible to tests so that the test can invoke them. For more details see <a href="https://vaadin.com/blog/is-mvp-a-best-practice-">Is MVP a Best Practice?</a><!--
--></li><li>Create factories for all UI components so that tests can mock the UI. See <a href="https://stackoverflow.com/a/10223964/104143">this answer on StackOverflow</a> for more details.<!--
--></li><li>Running integrated tests in a test bed to simulate <code>UI.​getCurrent()</code> or <code>VaadinSession.​getCurrent()</code>, e.g. using the <a href="https://github.com/mvysny/karibu-testing/tree/master/karibu-testing-v8">Karibu-Testing library</a>.<!--
--></li></ul><!--
--><b>LoginPresenter</b><br />
We used MVP as described in my <a href="/2020/02/tdd-classic-state-based-ui.html">previous article</a>. The group decided against a view model, because there was no specific UI model. Next was the presenter. The first two tests made us implement the requirement for a successful login: <i>User name and password given, button "Log in" clicked, back end reports success, then the form is closed.</i><!--
--><pre class="prettyprint lang-java">import org.mockito.Mockito;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class LoginPresenterTest {
public static final String USERNAME = "Peter";
public static final String PASSWORD = "Slovakia";
private AuthenticationService authenticationService;
private NavigatorView navigatorView;
private LoginView loginView;
private ExecutorService executorService;
private LoginPresenter loginPresenter;
@BeforeEach
public void init() {
authenticationService = Mockito.mock(AuthenticationService.class);
navigatorView = Mockito.mock(NavigatorView.class);
loginView = Mockito.mock(LoginView.class);
executorService = Executors.newSingleThreadExecutor();
loginPresenter = new LoginPresenter(authenticationService, navigatorView,
loginView, executorService);
}
@Test
public void should_call_backend_on_button_click() throws InterruptedException {
Mockito.when(authenticationService.authenticate(USERNAME, PASSWORD))
.thenReturn(new AuthenticationResult(true, "we do not care!"));
loginPresenter.login(USERNAME, PASSWORD);
waitForAuthentification();
Mockito.verify(authenticationService, Mockito.times(1))
.authenticate(USERNAME, PASSWORD);
}
@Test
public void should_navigate_on_login_success() throws InterruptedException {
Mockito.when(authenticationService.authenticate(USERNAME, PASSWORD))
.thenReturn(new AuthenticationResult(true, "we do not care!"));
loginPresenter.login(USERNAME, PASSWORD);
waitForAuthentification();
Mockito.verify(navigatorView, Mockito.times(1))
.navigateToDashBoard();
}
private void waitForAuthentification() throws InterruptedException {
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.SECONDS);
}</pre><!--
-->Using an <code>ExecutorService</code> made the asynchronous execution pretty simple. I like how they wrote two tests for the different aspects of successful login. Using smaller steps helped to get some logic sooner. It turned out that we needed another component for navigation, so we made up the <code>NavigatorView</code>. Then we went for the requirements <i>User name and password given, button "Log in" clicked, back end reports an error, show message in error line, form stays open</i> and <i>While the back end is working, the "Log in" button stays disabled.</i><!--
--><pre class="prettyprint lang-java">import org.mockito.InOrder;
import static org.mockito.ArgumentMatchers.any;
...
@Test
public void should_display_error_on_login_error() throws InterruptedException {
String errorMessage = "error message";
Mockito.when(authenticationService.authenticate(USERNAME, PASSWORD))
.thenReturn(new AuthenticationResult(false, errorMessage));
loginPresenter.login(USERNAME, PASSWORD);
waitForAuthentification();
Mockito.verify(navigatorView, Mockito.never())
.navigateToDashBoard();
Mockito.verify(loginView, Mockito.times(1))
.displayErrorMessage(errorMessage);
}
@Test
public void should_register_to_view() {
Mockito.verify(loginView, Mockito.times(1))
.addListener(any(LoginListener.class));
}
@Test
public void should_disable_button_while_backend_is_working() throws InterruptedException {
Mockito.when(authenticationService.authenticate(USERNAME, PASSWORD))
.thenReturn(new AuthenticationResult(false, "we do not care!"));
loginPresenter.login(USERNAME, PASSWORD);
InOrder inOrder = Mockito.inOrder(loginView);
inOrder.verify(loginView).setLoginButtonEnabled(false);
waitForAuthentification();
inOrder.verify(loginView).setLoginButtonEnabled(true);
}
}</pre><!--
-->The finished presenter class looked almost like the one for Swing.<!--
--><pre class="prettyprint lang-java">import java.util.concurrent.ExecutorService;
public class LoginPresenter implements LoginListener {
private final AuthenticationService authenticationService;
private final NavigatorView navigatorView;
private final LoginView loginView;
private final ExecutorService executorService;
public LoginPresenter(AuthenticationService authenticationService,
NavigatorView navigatorView, LoginView loginView,
ExecutorService executorService) {
this.authenticationService = authenticationService;
this.navigatorView = navigatorView;
this.loginView = loginView;
this.executorService = executorService;
loginView.addListener(this);
}
@Override
public void login(String username, String password) {
loginView.setLoginButtonEnabled(false);
executorService.submit(() -> invokeLoginService(username, password));
}
private void invokeLoginService(String username, String password) {
AuthenticationResult authenticate =
authenticationService.authenticate(username, password);
loginView.setLoginButtonEnabled(true);
if (authenticate.success) {
navigatorView.navigateToDashBoard();
} else {
loginView.displayErrorMessage(authenticate.message);
}
}
}</pre><!--
-->And the presenter would hide behind the <code>LoginListener</code> interface.<!--
--><pre class="prettyprint lang-java">public interface LoginListener {
void login(String username, String password);
}</pre><!--
--><b>Test Bed</b><br />
As for the Swing version, using a test bed helped testing the view. There is a useable Vaadin testing tool, the <a href="https://github.com/mvysny/karibu-testing/tree/master/karibu-testing-v8">Karibu-Testing library</a>. It worked out of the box, no special treatment necessary. We wrote tests that the view forwards actions to the <code>LoginListener</code>, i.e. the <code>LoginPresenter</code>, and that the view can display an error message.<!--
--><pre class="prettyprint lang-java">import com.github.mvysny.kaributesting.v8.MockVaadin;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import org.mockito.Mockito;
import static com.github.mvysny.kaributesting.v8.LocatorJ.*;
class LoginViewTest {
private final LoginViewImpl content = new LoginViewImpl();
@BeforeEach
void beforeEach() {
MockVaadin.setup(() -> new HelloUI(content));
}
@AfterEach
void afterEach() {
MockVaadin.tearDown();
}
@Test
void should_pass_on_button_click() {
LoginListener loginListener = Mockito.mock(LoginListener.class);
content.addListener(loginListener);
// simulate a text entry as if entered by the user
_setValue(
_get(TextField.class, spec -> spec.withCaption("Phone, email or username")),
"peter");
_setValue(
_get(TextField.class, spec -> spec.withCaption("Password")),
"Slovakia");
// simulate a button click as if clicked by the user
_click(_get(Button.class, spec -> spec.withCaption("Log in")));
Mockito.verify(loginListener).login("peter", "Slovakia");
}
@Test
void should_display_error_message() {
content.displayErrorMessage("myError message");
// simulate a text entry as if entered by the user
Label label = _get(Label.class, spec -> spec.withValue("myError message"));
Assertions.assertEquals(label.getStyleName(), "warning");
}
}</pre><!--
-->Satisfying these two tests gave us the following view:<!--
--><pre class="prettyprint lang-java">import com.vaadin.ui.*;
public class LoginViewImpl extends VerticalLayout implements LoginView {
private final TextField username = new TextField("Phone, email or username");
private final TextField password = new PasswordField("Password");
private final Button loginButton = new Button("Log in");
private final Label errorLabel = new Label();
public LoginViewImpl() {
addComponent(username);
addComponent(password);
addComponent(loginButton);
addComponent(errorLabel);
errorLabel.setStyleName("warning");
}
@Override
public void addListener(LoginListener loginListener) {
loginButton.addClickListener(clickEvent -> {
loginListener.login(username.getValue(), password.getValue());
});
}
@Override
public void displayErrorMessage(String errorMessage) {
errorLabel.setValue(errorMessage);
}
// ...
}</pre><!--
-->That was as far as we went during the sessions. We did not finish the whole login window, next tests would drive the logic of <code>setLoginButtonEnabled(boolean)</code>.<br />
<br />
<b>Conclusion</b><br />
Besides small differences, the code looks much like the <a href="/2020/02/tdd-classic-state-based-ui.html">Swing version</a>. The process worked the same, most tests do not deal with the UI. As I do not know many UI frameworks my conclusion is limited. Maybe - hopefully - probably this approach works for state based user interfaces as long as there is a reasonable test bed. I can see how it could work for <a href="https://docs.microsoft.com/en-us/dotnet/framework/winforms/">C# WinForms</a>. On the other hand, Vaadin and WinForms are very similar to Java's Swing. I need to look at <a href="/2020/03/tdd-immediate-mode-ui.html">other kind of user interfaces</a>.<br />
Peter Koflerhttp://www.blogger.com/profile/09597605582212160361noreply@blogger.com0