So, we have Cards with Suits and Ranks, we have a Deck, and we can draw random cards from it! Now it’s time to get some cards into the hands of the players!

Hands

Remember the rule we focused on last time:

A poker hand consists of 5 cards dealt from the deck.

We didn’t do anything with a poker hand yet, so let’s go and create it. We start off simple with our first failing test:

1

2

3

4

5

6

classHandTests: XCTestCase{

functestEmptyHand(){

lethand:Hand=Hand(cards:[])

XCTAssert(hand.numberOfCards==0)

}

}

Next, the implementation to make our test pass, which is easy enough. We give the Hand a set of cards, and the Hand number should be 0:

1

2

3

4

5

6

7

publicstructHand{

public varnumberOfCards: Int{

return0

}

init(cards:[Card]){}

}

The test passes, but we haven’t really done anything yet, so lets continue with another test.
What test could we add to make the implementation more sensible? One that tests one card instead of none, why not.

1

2

3

4

functestOneCardInHand(){

lethand:Hand=Hand(cards:[Card(suit:.Club,rank:.Ace)])

XCTAssert(hand.numberOfCards==1)

}

We have to change our code a bit:

1

2

3

4

5

6

7

8

9

10

11

publicstructHand{

private letcards:[Card]

public varnumberOfCards: Int{

returncards.count

}

init(cards:[Card]){

self.cards=cards

}

}

Nothing special here. We add an array, we store the parameter from the constructor into the property and in the calculated property numberOfCards we return cards.count. Test passes 🙂

So how are we going to determine which hand is better? We need some kind of evaluation. Lets look at the rules again to see what they say.

Poker hands are ranked by the following partial order from lowest to highest: High Card, Pair, Two Pair, Three of a Kind, Straight, Flush, Full House, Four of a Kind, Straight Flush, (and Royal Flush).

Alright. Lets start with the first one, the High Card.

High Card

Hands which do not fit any higher category are ranked by the value of their highest card. If the highest cards have the same value, the hands are ranked by the next highest, and so on.

Lets first write a test that evaluates our hand to a high card. When is this the case? Well, when a hand only has one card, it is a high card by definition. Lets write a test to reflect this.

1

2

3

4

5

functestSingleCardHandStrengthIsHighCard(){

lethand=Hand(cards:[Card(suit:.Club,rank:.Ace)])

XCTAssert(hand.evaluate()==.HighCard)

}

Looks easy enough, but I made some presumptions. I’d thought to make an enum for the hand strengths we have, one of them being .HighCard. We need an evaluate function that returns that .HighCard.
Heres how the enum looks:

Note that we back the HandStrength with an Int. This way we can use comparison, which means that HighCard < Pair and StraightFlush > Straight. Now lets create the evaluation function, which is super straightforward for now:

1

2

3

4

5

...

public funcevaluate()->HandStrength{

return.HighCard

}

...

Easy does it!
But what if we compare two hands, both of which are high cards? Our evaluate function will just return us that the hand is of strength high card, so if we compare the two, they would be equal. However, it doesn’t differentiate between a high card ten and high card ace, while according to the rules the ace would win right?
So we need something to compare hands with based on more than the hand strength. Lets write a test to capture this.

1

2

3

4

5

6

functestThatHighCardAceBeatsHighCardTen(){

lethandA:Hand=Hand(cards:[Card(suit:.Club,rank:.Ace)])

lethandB:Hand=Hand(cards:[Card(suit:.Club,rank:.Ten)])

XCTAssert(handA>handB)

}

Now it gets interesting! What is going on here? How are we going to make this test pass? The compiler gives us a hint already. It says “Binary operator ‘>’ cannot be applied to two ‘Hand’ operands”. How can we solve this? We need some way to make two hands comparable. Whats great about Swift is that there is a protocol for this. It is called Comparable.

Lets look at how to implement it. We are first going to create an extension on Hand and make it conform to Comparable:

1

extensionHand: Comparable{}

XCode again will give us a hand here; it gives an error and a possible fix, so lets go with that. It provides us two stubs for functions. Looks familiar doesn’t it?

1

2

public staticfunc==(lhs:Hand,rhs:Hand)->Bool{}

public staticfunc<(lhs:Hand,rhs:Hand)->Bool{}

Comparable actually inherits from the protocol Equatable, and so the ‘==’ actually is required by Equatable instead. Let’s take a step back and define a test for this first, commenting out our testThatHighCardAceBeatsHighCardTen test for a moment and removing the extension adopting Comparable for a bit.

Here is our new test. Two hands are the same if they hold cards that have the same value:

1

2

3

4

5

6

functestThatHighCardsWithEqualRanksAreEqual(){

lethandA:Hand=Hand(cards:[Card(suit:.Club,rank:.Ace)])

lethandB:Hand=Hand(cards:[Card(suit:.Heart,rank:.Ace)])

XCTAssert(handA==handB)

}

Now lets adopt Equatable for hand to pass our test:

1

2

3

4

5

extensionHand: Equatable{

public staticfunc==(lhs:Hand,rhs:Hand)->Bool{

returnlhs.cards[0].rank==rhs.cards[0].rank

}

}

This makes our test pass, but as soon as our hand holds more cards we are going to be in trouble. Lets add another test to capture this:

And so we have to loop over the cards in the hands and compare each one as such, where we use a handy function in swift called zip, which creates an array of tuple pairs for each entry of handA and B together:

1

2

3

4

5

6

7

8

9

public staticfunc==(lhs:Hand,rhs:Hand)->Bool{

for(lhsCard,rhsCard)inzip(lhs.cards,rhs.cards){

iflhsCard.rank!=rhsCard.rank{

returnfalse

}

}

returntrue

}

But we aren’t there yet. If we change our test a little, we can see why.

In order to fix this, we simply need to order our cards before comparing them. We define a sort function which sorts our cards high to low, and use that to sort both lhs.cards and rhs.cards using sorted(by:):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

public staticfunc==(lhs:Hand,rhs:Hand)->Bool{

letsortByRank:(Card,Card)->Bool={cardA,cardB in

returncardA.rank.rawValue>cardB.rank.rawValue

}

letlhsCards=lhs.cards.sorted(by:sortByRank)

letrhsCards=rhs.cards.sorted(by:sortByRank)

for(lhsCard,rhsCard)inzip(lhs.cards,rhs.cards){

iflhsCard.rank!=rhsCard.rank{

returnfalse

}

}

returntrue

}

Our test passes! We can actually simplify this a bit further, so lets refactor a bit. Using what we’ve just learned, we can define Comparable for Card.

1

2

3

4

5

extensionCard: Comparable{

public staticfunc<(lhs:Card,rhs:Card)->Bool{

returnlhs.rank.rawValue<rhs.rank.rawValue

}

}

We can now replace our sort function in the Hand extension for Equatable as such, because operators are actually defined as a function!

1

2

3

4

5

6

7

8

9

10

11

12

public staticfunc==(lhs:Hand,rhs:Hand)->Bool{

letlhsCards=lhs.cards.sorted(by:>)

letrhsCards=rhs.cards.sorted(by:>)

for(lhsCard,rhsCard)inzip(lhs.cards,rhs.cards){

iflhsCard.rank!=rhsCard.rank{

returnfalse

}

}

returntrue

}

Awesome. How does this work? We’ve defined functions for == and < , so Swift is now able to infer the other cases as well; >=, < =, > and !=. Lets check if our tests still run.

Green!

Remember we still have one commented test. Lets uncomment it. You probably already figured now how to make this test pass; we have to adopt Comparable on Hand again. It’s slightly different from the Equatable function; we’re only interested in cases where the ranks are different, hence we check if two cards have the same rank, and if so, we continue.

Note that we actually have to compare rank (lhsCard.rank == rhsCard.rank), as our == function on Card also compares suit, and would give false where the ranks are the same but the suits are not. If they’re not the same, then we return lhsCard < rhsCard. If all cards are the same, then < is obviously false:

1

2

3

4

5

6

7

8

9

10

11

12

extensionHand: Comparable{

public staticfunc<(lhs:Hand,rhs:Hand)->Bool{

letlhsCards=lhs.cards.sorted(by:>)

letrhsCards=rhs.cards.sorted(by:>)

for(lhsCard,rhsCard)inzip(lhsCards,rhsCards){

iflhsCard.rank==rhsCard.rank{continue}

returnlhsCard<rhsCard

}

returnfalse

}

}

And our test passes! Great!

We’ve covered a lot again, making use of zip and sorted(by:) and implementing Comparable to make things easier for us. Next time we’re going a bit further to see if we can detect any other hand strengths as well, like Pairs, Straights and Flushes.

Share this:

So previously we’ve created a simple deck of cards. Now its time to go a bit further and actually do something useful with those. Lets add the Hand!

We’re still doing the kata, of which the rules say the following about a hand:

A poker hand consists of 5 cards dealt from the deck

Cool, so cards are dealt from the deck! Bet you didn’t saw that one coming 🙂 How do we capture this in a test?

What we can do is test if the number of cards go down when we draw a card. Let’s take our singleDeck() of cards, draw a card, and test if the amount of cards go down:

1

2

3

4

5

6

7

8

9

classDeckTests: XCTestCase{

...

functestDrawCard(){

letdeck=Deck.singleDeck()

deck.drawCard()

XCTAssert(deck.numberOfCards==51)

}

...

}

How would we make that test pass? Easy enough:

1

2

3

4

public funcdrawCard(){

ifcardsInPile.count==0{return}

cardsInPile.remove(at:0)

}

Oh wait! Remember from the previous blog post that when we are mutating, we should use ‘var’ and not ‘let’ right? The compiler will tell us that cardsInPile is immutable, so let’s change it to var.

Now, we don’t get a card back, let alone test if that card is actually removed from the deck. It’s not very useful yet. Let’s try to improve on that by writing another test, that allows us to verify if a card is still in the deck or not.

1

2

3

4

5

6

7

8

9

classDeckTests: XCTestCase{

...

functestThatCardIsInDeck(){

letdeck=Deck.singleDeck()

letcard=Card(suit:.Spade,rank:.Ten)

XCTAssert(deck.contains(card))

}

...

}

Next, our implementation, which is pretty straightforward. Array has a contains function which takes a closure which provides an element and returns a boolean:

1

2

3

4

5

public funccontains(card:Card)->Bool{

returncardsInPile.contains{cardInPile in

card.rank==cardInPile.rank&&card.suit==cardInPile.suit

}

}

We can simplify this by refactoring a bit. We can actually make use of a protocol called Equatable. If we make Card adopt Equatable, we can move this piece of code there. Lets create an extension on Card and adopt Equatable:

1

extensionCard: Equatable{}

XCode will give an error, and will tell us to implement the curious looking function ==(lhs: Card, rhs: Card) -> Bool. How cool is this!? We can actually define the == operator for our Card!

1

2

3

4

5

extensionCard: Equatable{

public staticfunc==(lhs:Card,rhs:Card)->Bool{

returnlhs.rank==rhs.rank&&lhs.suit==rhs.suit

}

}

Having implemented this, we can now simplify our contains function:

1

2

3

public funccontains(card:Card)->Bool{

returncardsInPile.contains(card)

}

Cool! Now we can also check if the card we’ve drawn is no longer in the deck:

1

2

3

4

5

6

functestThatDeckDoesntContainDrawnCard(){

letdeck=Deck.singleDeck()

letcard=deck.drawRandomCard()

XCTAssertFalse(deck.contains(card:card))

}

For that to work we need to rewrite our drawCard() method a bit, as we now need to return a card. Theres a little caveat, because what if the deck has been emptied? Lucky we can define this in Swift, returning an optional Card (Card?). When we don’t have any cards, we just return nil, else we return the card we remove:

1

2

3

4

public funcdrawCard()->Card?{

ifcardsInPile.count==0{returnnil}

returncardsInPile.remove(at:0)

}

Our test needs to deal with this as well. Our card is now of type Card?, not Card. The contains method takes a Card, so how do we match that up? There are two ways to do it; the safe way and the unsafe way. Since this is a test, we want a failure as soon as possible, so we’ll go with the unsafe way; we force cast our optional Card? to a Card by using an exclamation mark:

1

2

3

4

5

6

functestThatDeckDoesntContainDrawnCard(){

letdeck=Deck.singleDeck()

letcard=deck.drawCard()

XCTAssertFalse(deck.contains(card:card!))

}

Great! The test passes! We’ll discuss how to go about optionals in a safe way later, as force casting an optional that is nil will result in a crash. Something we would really like to avoid in our real application.

Note that the compiler currently warns us that for the testDrawCard() test, the result of call to ‘drawRandomCard()’ is unused. We can easily fix this by prefixing the method with @discardableResult:

1

2

3

@discardableResult public funcdrawCard()->Card?{

...

}

Running the test again will now no longer show the compiler warning, awesome!

So let’s recap. We can draw a card and check if a card is in the deck (or not), but we still always get the first card that is still in the deck. We would first get a ♦️2, then ♦️3, etc. To get a random card, we need to either randomise our draws or shuffle our deck. Intuitively, randomising our draws seems least effort. We just pick a random number the size of the deck and take that card out of the array. But how would we test it? Random does imply that you don’t know which card comes next, right? Well, we can go around that by using the same seed for the random number generator in our test. We’re going to utilise GKARC4RandomSource and as you can see, it takes a Data object as a seed. Let’s define our test:

Let’s see if we can change the code to accommodate this. Our singleDeck() method doesn’t change much, we add a seed parameter of type Data?, and we default it to nil:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

publicclassDeck{

...

classfuncsingleDeck(seed:Data?=nil)->Deck{

varcards=[Card]()

forrankValue in2...14{

forsuitValue in0..&lt;4{

letsuit=Suit(rawValue:suitValue)!

letrank=Rank(rawValue:rankValue)!

cards+=[Card(suit:suit,rank:rank)]

}

}

returnDeck(cards:cards,seed:seed)

}

...

}

Next, we add the seed parameter to the initialiser, also defaulting to nil. We then add a property randomNumberGenerator of type GKARC4RandomSource, which we create in the initialiser using the seed. The so-called nil coalescing operator (??) picks between our optional parameter or the current date if our optional parameter is nil:

1

2

3

4

5

6

7

8

9

10

11

12

publicclassDeck{

private varcardsInPile:[Card]

private letrandomNumberGenerator:GKARC4RandomSource

init(cards:[Card],seed:Data?=nil){

self.cardsInPile=cards

letseed=seed??Date().description.data(using:.utf8)!

randomNumberGenerator=GKARC4RandomSource(seed:seed)

}

...

}

Finally, we are going to change our drawCard() method. We ask the random number generator for a new Int at every draw. Notice that we pass in an upper bound that is the size of the array of cards, this makes sure that we pick a number in the right range, and not for example 53 while our deck is only 52 cards:

1

2

3

4

5

6

7

8

publicclassDeck{

....

@discardableResult public funcdrawCard()->Card?{

ifcardsInPile.count==0{returnnil}

letrandomIndex=randomNumberGenerator.nextInt(upperBound:cards.count)

returncardsInPile.remove(at:randomIndex)

}

{

And now the test passes again, great!

But how do I knew what cards to check against? I didn’t. I tried the test and printed randomCards to see what the outcome was, which arguably isn’t that good of strategy. So how can we make sure it’s actually random? We could try different seeds and check if the cards are different:

Pfew, the test passes, nice! Testing for random is generally not a good idea, as you can never know what to test against. There are some techniques to help test code that use random numbers, but that involves a more advanced technique called mocking. I probably won’t cover mocking in this series.

That is it for today! As you can see, we took some smaller steps and some bigger steps. TDD is all about thinking up that next step. If you feel confident, you can take a bigger step. If you feel that you’re not in control or working on something intricate, you can choose to take smaller steps. Meanwhile, we’re getting to know Swift better and better.

Next time we’re going to take a look at how we can evaluate hands of cards!

Share this:

Earlier I talked about the poker hands kata to practice our coding. Today we’re going to start easy.
Here is the first line in the rules:

A poker deck contains 52 cards – each card has a suit which is one of clubs, diamonds, hearts, or spades (denoted C, D, H, and S in the input data). Each card also has a value which is one of 2, 3, 4, 5, 6, 7, 8, 9, 10, jack, queen, king, ace (denoted 2, 3, 4, 5, 6, 7, 8, 9, T, J, Q, K, A). For scoring purposes, the suits are unordered while the values are ordered as given above, with 2 being the lowest and ace the highest value.

I’ve annotated the rules, and put the main concepts in bold. These are Deck, Card, Suit and Value. So how can we represent these? A Deck obviously consists of Cards, and each Card always has both a Suit and a Value.

Cards

Lets talk about Cards first! We have 52 unique cards, and thus we note that there is a limit to the amount different values a Suit and a Value can have. We only have four possible Suits, and of each Suit we only have thirteen different Values. We could have each Suit and Value represented by an Integer. Say for Suit we have the numbers 0-3. What happens if we accidentally create a card with a Suit outside this range? Is it then invalid, or are we going to modulo to make it work? We would need a lot of extra code to deal with these edge cases, just to make our code reliable. Lucky we don’t have to, as Swift provides us with a concept in which we can limit the amount of values to exactly the amount we need, using Enums.

Enums in Swift are, opposed to in Objective-C, one of the core concepts (or first class citizens as we call them), next to classes, structs and functions. While Integer can represent any number from 0 to 18.446.744.073.709.551.615, enums can have only as much different values as defined by the enum cases. This is useful, because we then don’t have to care if a certain value is invalid or not, or how to deal with such cases otherwise. Having a finite number of possible values makes Suit and Value ideal enum candidates.

Lets start off first by creating a Single View project, and don’t forget to add the test target. Since it’s a kata we follow the rules of TDD, and thus we start by writing our first failing test:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

importXCTest

@testable importPokerHands

classCardTests: XCTestCase{

functestSuitAndRank(){

letcard=Card(suit:Suit.Diamond,rank:Rank.Jack)

XCTAssert(card.suit==Suit.Diamond)

XCTAssert(card.rank==Rank.Jack)

}

}

We create a Card which is initialised by a Suit and a Rank, and we test if the Suit is what we expect, being a Diamond. We run the test and it fails, because we haven’t implemented anything yet. So what do we need to implement this? Lets start off by creating a Card:

1

2

3

4

publicstructCard{

letsuit:Suit

letrank:Rank

}

So do we have everything we need? Lets run the test again. It fails, because we still haven’t defined Suit and Rank. Lets do that as well:

1

2

3

4

5

6

publicenumSuit{

caseDiamond

caseHeart

caseClub

caseSpade

}

1

2

3

4

publicenumRank{

caseTwo,Three,Four,Five,Six,Seven,Eight,Nine,Ten

caseJack,Queen,King,Ace

}

Lets try our test again. It passes! Awesome.

Deck

Lets continue building on this, here is our new failing test in which we create an empty deck. We expect the number of cards to be 0.

1

2

3

4

5

6

classDeckTests: XCTestCase{

functestEmptyDeck(){

letdeck=Deck()

XCTAssert(deck.totalNumberOfCards==0)

}

}

To make it work, we need to create a deck, and have a computed property totalNumberOfCards that returns 0. Let’s create it. Computed properties don’t hold any value, they’re always computed and thus have a body. They’re actually very similar to a function/method. There are no rules for when you should use a computed property and when a function. My tip: as soon as there is some complicated logic going on, you might just want to have a function. That conveys that its not just a property, and that there is more to it than just returning a value.
Also note that computed properties are always ‘var’. We’ve only used ‘let’ until now, so I need to explain this further. ‘let’ means that the value or variable cannot change, i.e. mutate. ‘var’ means variable (obviously), so it is either computed or can be changed. We’ll see some more of ‘var’ later.

1

2

3

4

5

6

publicstructDeck{

public vartotalNumberOfCards: Int{

return0

}

init(){}

}

Great! The tests pass again. Note that we only did the most limited change possible to make the test work. This is important to realise.
Of course a deck should also hold cards, so let’s make that work as well. Let’s add a test for that:

1

2

3

4

5

6

...

functestDeckWithOneCard(){

letdeck=Deck(cards:[Card(suit:.Diamond,rank:.Ten)])

XCTAssert(deck.totalNumberOfCards==1)

}

...

We need to change a few things to make it work. First of all, we will need an initialiser that takes an array of cards. Second, we need to store the array of cards and let totalNumberOfCards return the amount of cards in the array. Our Deck is going to look like this:

1

2

3

4

5

6

7

8

9

10

11

12

13

publicstructDeck{

private letcardsInPile:[Card]

public vartotalNumberOfCards: Int{

returncardsInPile.count

}

init(){}

init(cards:[Card]){

self.cardsInPile=cards

}

}

Pass!
Finally, we want to have a deck of 52 cards. It is going to be a bit of a hassle to create every card in the code manually, so lets write a convenience method for it. First the test:

1

2

3

4

5

6

...

functestSingleDeck(){

letdeck=Deck.singleDeck()

XCTAssert(deck.totalNumberOfCards==52)

}

...

Then the implementation. To make it easier to instantiate all the different cards we need, we need something convenient. What if we could create a loop? Unfortunately we cannot just ask the enum to loop over all of its cases. If only they could be Ints instead, then it would be easy right? Swift has a way to accomplish that. We can back an enum by an Int as such:

1

2

3

4

5

6

public enumSuit: Int{

caseDiamond

caseHeart

caseClub

caseSpade

}

We do the same for Rank, and we make sure that Two = 2, so that all the following cases have the correct value. Ace will have value 14. That also makes us check off the rule that the values are ordered as given above, with 2 being the lowest and ace the highest value.

1

2

3

4

public enumRank: Int{

caseTwo=2,Three,Four,Five,Six,Seven,Eight,Nine,Ten

caseJack,Queen,King,Ace

}

The addition of the Int backing also gives us a failable initialiser for the enum: init?(rawValue: Int). Initialising a Suit with a rawValue gives us either a valid Suit or nil, which is captured in a concept called Optional. Actually Optional is an enum by itself and conforms to ExpressibleByNilLiteral, so that .none returns nil:

1

2

3

4

enumOptional{

case.some(Value)

case.none

}

On to our Deck class, we add a class func singleDeck(), which creates an array of cards, and fills them using the values we’ve just set on our Int backed enums. We also need to change our Deck from a struct to a class because of this:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

publicclassDeck{

...

classfuncsingleDeck()->Deck{

varcards=[Card]()

forrankValue in2...14{

forsuitValue in0..<4{

letsuit=Suit(rawValue:suitValue)!

letrank=Rank(rawValue:rankValue)!

cards+=[Card(suit:suit,rank:rank)]

}

}

returnDeck(cards:cards)

}

...

Green!
Remember we talked about how ‘var’ allows for the variable to change? Here’s a perfect local example. We initialise an empty cards array and by looping over it we add new cards to the array, therefore mutating the cards array.
There is a rule to using var though; we only make a property or variable var, if we actually mutate. The compiler is really great and will help in this by informing you that you’ve used a ‘var’ but no mutation took place, and that you should be using a ‘let’ instead.

Thats it for now!
Next time, we’ll go into drawing cards from the deck!

Share this:

It has already been like 6 months since I announced I would make a fresh start given I would have to make some time for it. Lets do it!

Swift 2.1 got introduced a week or two ago, and the time comes closer that we are going to drop Objective-C in favour of it. You might wonder why the heck after a year of Swift we are still using Objective-C, but the answer is quite simple. Given that we have a large user base, we still provide extensive support for iOS 7 on all of our apps. They share a large code base in multiple static libraries. As you might know, you can’t really pack swift code in static libraries, and dynamic frameworks only came available in iOS 8 (There is of course the CocoaPods workaround, but we’ve decided against using it). We couldn’t therefore afford to abandon Objective-C just yet. As iOS 9 adoption rate grows and that of iOS 7 dwindles though, the time draws closer to finally drop iOS 7 support and leap into the future.

So here we are. Lets start with Swift!

Before we start, we are going to have to think up a project. Most people would probably make some kind of example app, but not me. I’ve been reading The Clean Coder (I’ll do a post on some nice new books i’ve read soon) by Uncle Bob Martin a while ago, and he proposed to do coding katas on a regular basis to hone your programming skills. The idea is presumably first coined by one of the writers of another quite famous book, The Pragmatic Programmer. There are a few websites that collect katas, and there are those that go a step further and build a whole suite around them. One I have to mention is Code Wars, which has literally dozens and dozens, provides a ranking and honour system, and allows you to take it up against others as well in the process.

For now, we’ll do with picking one from Coding Dojo and start with the Poker Hands Kata. In the next post we’ll start coding.

Share this:

Im aware I’ve left this blog bare for the previous few years. I’ve decided it is high time to do something with it again.

I’ve been working in the mobile industry for the past few years, so I have some new ideas for topics regarding iOS development mainly, and Android development secondly. Next, we are currently deploying scrum in our organisation, so i’ll give some insights in how that works. Furthermore I’ve been exploring some new hobbies, so expect some posts on board games, running, cycling and hiking.

Enough to talk about, now lets find the time to write it down as well 😉