Design space

Yesterday I read this article, from Derek Sivers’ blog. I encourage you to read it as well, but here’s the summary:

  • We should move logic more into the database, because “Classes, models, and methods (OOP) are an unnecessary complication.”
  • Data structure doesn’t change often, but code (logic) does. So let’s move the logic closer to the data structure
  • “PL/pgSQL is not the most beautiful language, but the simplicity of having everything in the database is worth it.”
  • We can do that by using triggers, stored procedures and the likes. We then call them directly from the application layer (there follows an example of a REST api in sinatra).

First I thought it was a long winded joke, but the article was over before the expected “haha jk”. I actually had to scroll down quite a bit to find the first dubious commenter.

Now, let’s clarify one thing: his approach makes sense – under very specific conditions. Those conditions loosely being that the application is mostly data centric (data in, data out, CRUD and a little validation), and most of the work is related to how data is presented.

Fact is, we have already the perfect solution for this scenario, and we have had it for years: it’s called Microsoft Access.

So, why aren’t all applications out there written in MS Access, or one of its clones?

Enter: design space

So, what is the problem with having all the logic in the database?

Anyone who’s actually worked on a big application, with hundreds of triggers and stored procedures, knows perfectly what the problem is. It might be slightly more difficult to articulate it in clear words – I myself could not place a finger on the definition for a long time.

When you decide to store all logic in the database, you have made the decision to fight in a very tight space. Everytime something unexpected pops up, you have to work it out inside the very cramped code room you’ve created for yourself.

The advantage is that everything is in reach – add, delete, change a trigger here and a stored procedure there, you can alter a great deal of things with very little code.

The disadvantage is that you’re effectively coding yourself into a corner. Moving is impossible except by making very complicated contorsions. Everytime you do, you’re at risk of breaking something you didn’t want to touch at all. Side effects galore.

And, the more you do this, the more space you’re taking away from yourself – the room becomes more and more cramped with each trigger and each stored procedure you add. It turns effectively into the same OOP-bound complexity Sivers mentions – without the room needed to work the complexity out.

The reason why OOP (or really, anything that tries to handle this kind of complexity in a different way) exists is to give us programmers space. Yes, having to make data flow through different layers makes more work. Yes, you have to change lots of things every time something deep in the database changes.

It’s a tradeoff – what you get back from it is all the joints, the clean points of connection, the interfaces you can program against. If you do things right, you can make yourself all the room you need to solve a specific problem. Yes, maintaining those joints is work. It doesn’t mean that it’s automatically better to get rid of them.

So, if you know for a fact you do not need the design space, you can save yourself some time and some effort by storing your logic in the database or, even better, using some kind of MS Access clone – since there is not much logic for you to write anyway, it’s better to have something pre-made do the heavy lifting.

But at the same time, if you don’t need the design space, it is probably the case that your project does not need ad-hoc software and you are much better off buying something existing.

Which strategy to choose should be a conscious decision, to be taken for each organization and for each project inside of it. If you’re a senior programmer, that is the kind of decision you should be able to take. The fact that there seems to be absolutely no clue inside the community about seemingly simple topics like this one is, honestly, a bit scary.

Advertisements

What do League of Legends and working in IT have in common?

So, I now live in Norway and my sister now lives in Belgium. That makes it harder to keep in contact. One way to mitigate is of course to find a common activity to do together – and that’s how I started playing League of Legends. The game is played 5v5, on a fixed map. For someone that is used to see patterns everywhere, the similarities with life and work in IT are evident:

Skill is paramount

So you’re a successful professional. You’re smart, you’re experienced, your certifications are plenty. Still Mateusz, from Gdansk, 14, who has supposedly had repeated intercourse with your mother last night and is somehow well informed about your father’s sexual preferences, is better than you. By a lot. He (literally) runs circles around you and you’re there, hugging your tower, having to choose between letting him outfarm you to oblivion or feeding like there’s no tomorrow.

You are a successful professional, you’re smart, you’re- doesn’t matter: you’re getting pwnd, and that’s the end of it.

And that’s because he’s better than you. Yes, a 14-years old is better than you. Why is irrelevant – yes, he probably plays LoL all day – it does not matter. Still better than you. Acknowledge that, try to learn from the little bugger, and do not overextend. He’s gonna rape you, exactly like he said.

Respect skill. Learn to recognize and acknowlegde skill properly – skilled people might not be the people you would want them to be, or people you like. Don’t let irrelevant factors influence your judgement – or else, you’re going to pay for that mistake dearly. If you judge people on your team by any other metric, you’re going to fail. Skilled people are what make or break a project – forget that and you’re going to have a bad time.

Hire for skill, manage towards maximizing potential. Everything else is a second thought.

Taken skill for granted, teamwork is king

A very convenient (if you’re an occasional player) mechanic of LoL PvP is that your performance will be analyzed by the game and, based on that, the matching engine will try its best to put you against people on your skill level – which makes encounters with smurfs like the one previously mentioned a somewhat rare occurrence, thus offering a much more pleasant gaming experience for n00bz like me.

The first interesting thing you will notice once you’re matched against people with your skill level is how much of a difference teamwork makes: teams in which people call for MIAs, ping and ward consistently, and try to coordinate towards dragon, baron and major objectives are much more successful than teams who do not: try to stop the enemy team from taking inner mid 5v2 with the other three scattered across the map, with no aim and absolutely no intention to heed your desperate help mid plz, and you’ll know what I’m talking about.

Dying in a 2v5 fight with 3 assists is good team play. Ganging up 3v1 on an enemy and then spamming the chat with ksno you ks is not. The former are people you want in your team. The latter probably have a brilliant career in management ahead of them.

Truman said:

It’s amazing what you can accomplish when you do not care who gets the credit

That’s the definition of teamwork – it’s the magic that happens when nobody cares about who takes the credit. No, it’s not a measure of how much middle management likes you (while that would certainly help you more with your career than being a real team player). And no, it’s not that thing which shields you from your individual responsibilities. It’s a much less rewarding experience than the people in charge would like you to think it is – especially when it comes to your personal interest. So, if you are seriously up for being a true team player, make sure that your organization really values and rewards team players.

Again, this is all assuming that the skill is actually there. Otherwise you’re all wasting time and money. No matter how coordinated you are, an enemy diamond smurfing on the enemy team will just make minced meat of all of you – single handedly. So, better to try and get some of those on your team first. After you’ve managed to do that, you can worry about how can you better make the team work together. The order is important here.

If you can, carry

The convenient mechanic i mentioned earlier: it’s not flawless. That means you will most likely be matched with people in same league as yours but, even inside the same league, skill level varies wildly. As a consequence, there’s a chance that you might find yourself being the best player on your team.

As the best player in the team you have an implicit responsability, apart from winning your lane: you have to make sure that the advantage you build by outplaying your lane opponent is somehow shared by the other, weaker, members of your team: you might be the best player on SR, you might be winning mid 5-0 but if in the meantime your teammates lose bot and top, feed like crazy and generally throw the game you’re
not going to be able to face the extremely fed enemy carries 3v1 or even 2v1 late game.

So, in order to avoid the situation, change lane when your opponent is dead and try to be as helpful as possible – that’s what win games. Losing some cs in order to keep outer bot/top up is worth it.

(Again, that’s assuming you’re actually on the same order of magnitude of the other players when it comes to skill. If you’re smurfing, winning the game singlehandedly is faster than trying to help the helpless. Skill rules, always.)

Letting your coworkers struggle for days on a problem that would take you an hour or so is ultimately not good for you – yes, even if that’s not your job.

If you’re the carry: roam a lot, help where it’s needed, and be generally available – even if it costs you some time of your own. It’s worth it.

If you can’t, let others carry you

Same situation, but opposite role – you‘re the weak link. You call Ryze mid, you find a Cassiopeia on the other side and, on top of the bad matchup, she’s better than you… gg? Well, not if you keep your ego in check. Hug your tower, farm what you can from there, and for christ’s sake do not feed. You don’t have to win the game all by yourself: there’s four other players on your team.

You’re in a bad spot, sure. You don’t have to throw the game because of it. Acknowledge that you’re outplayed, play safe, and entrust your teammates with the game. If you try to punch above your weight, you’re going to hurt the team (and your collective chances at winning) much more than if you play passively.

If you find yourself struggling with a design and you can’t get out of it no matter how much you try, call for help. If you “brilliant ideas” routinely end up being unmaintainable bundles of spaghetti code, call for help. There’s other people in your team, working with you, they might be better than you at that task even if you’re more experienced, or more senior, or (god forbid) appointed as the architect by management’s decree. lol im diamond smurf give me mid doesn’t usually end well, especially if you’re not really “diamond smurf”. Keep your ego in check – skill should decide hierarchy, the most skilled people should make the calls. That’s for the well being of the whole organization.

Play the meta

So you’re playing a decent Ryze mid, 6-2 so far with a good gold advantage, tear and RoA fully stacked, boots and frozen heart completed. The enemy Garen struggles a lot when you burst him and has escaped the last gank, but just barely. Time to buy  archangel and go full offensive, as usual when it comes to mid game – tear is stacked and the resulting seraph gives you enough burst to blow up the entire enemy team from your fountain, plus the shield for when things go south. It’s just too good to even consider the alternatives.

Garen goes MIA for 5 mins or so, and the next time you see him you jump in for the kill… and he mauls you. WTF?

You try again, and again, and you go 6-5, from 6-2 in a matter of minutes. What happened?

Well, what happened is that Garen saw that coming, and bought tons of MR. So your burst now gives him the tickles. Too bad you didn’t even think about it and blindly followed your usual item progression path – if you bought a void staff instead of archangel you would have still had the upper hand, thanks to that sweet sweet MP. So your team loses, and you only have your zealotry and your inability to read the environment to blame.

Different situations call for different strategies, different tools and different mindsets. There’s no silver bullet, no matter how much one might look like it. Learn that, and use it to your advantage: having experience with lots of different tools and being able to be effective in a lot of coding styles makes you extremely valuable for an organization.

Programming challenges – War!

The book programming challenges is one I see recommended quite often – so, I decided to give it a try. The first problem I’ve encountered involves replicating a children’s card game called war, which I’d honestly never heard before. The problem is stated as such:

A standard 52-card deck is dealt to two players (1 and 2) such that each player has 26 cards.
Players do not look at their cards, but keep them in a packet face down.
The object of the game is to win all the cards. Both players play by turning their top cards face up and putting them on the table.
Whoever turned the higher card takes both cards and adds them (face down) to the bottom of their packet. Cards rank as usual from high to low: A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, 2.
Suits are ignored.
Both players then turn up their next card and repeat.
The game continues until one player wins by taking all the cards.
When the face up cards are of equal rank there is a war.
These cards stay on the table as both players play the next card of their pile face down and then another card face up.
Whoever has the higher of the new face up cards wins the war, and adds all six cards to the bottom of his or her packet.
If the new face up cards are equal as well, the war continues: each player puts another card face down and one face up.
The war goes on like this as long as the face up cards continue to be equal.
As soon as they are different, the player with the higher face up card wins all the cards on the table.
If someone runs out of cards in the middle of a war, the other player automatically wins.
The cards are added to the back of the winner’s hand in the exact order they were dealt, specifically 1’s first card, 2’s first card, 1’s second card, etc.

Nothing complex so far. So, I scroll down to see the solution and I’m welcomed by this snippet:

#define NCARDS 52 /* number of cards */
#define NSUITS 4 /* number of suits */

char values[] = "23456789TJQKA";
char suits[] = "cdhs";

int rank_card(char value, char suit)
{
    int i,j; /* counters */
    for (i=0; i<(NCARDS/NSUITS); i++)
        if (values[i]==value)
            for (j=0; j<NSUITS; j++)
                if (suits[j]==suit)
                    return( i*NSUITS + j );
    printf("Warning: bad input value=%d, suit=%d\n",value,suit);
}

Ugly! 5 (FIVE) levels of nesting! I understand that it’s C we’re talking about here but that seems a bit more complex than it should be. I stopped right there and rolled my own solution in Ruby (yeah, I’ve got nothing better to do tonight). This is the result:

Let’s define some constants first:

A = 14

SPADES = :s
DIAMONDS = :d
HEARTS = :h
CLUBS = :c

SUITS = [SPADES, DIAMONDS, HEARTS, CLUBS]

We’ll have to deal with cards – so let’s define a class for them

class Card

  attr_reader :rank
  
  def initialize(rank, suit)
    @rank = rank
    @suit = suit #unused
  end
    
end

Modelling the card like this (with a rank and a suit) makes little sense but the problem specification suggested to do so (as does the C snippet above), so that’s it – cards could have been integers.

Cards will have to be divided into two decks, from which we’ll have to draw and to which we’ll have to add conquered cards. Let’s make a class for them as well. Its methods are quite self explanatory.

class Deck

  def initialize(cards)
    @cards = cards
  end
  
  def draw
    return @cards.pop
  end
  
  def collect(stack)
    while(!stack.empty?) do
      @cards.insert(0, stack.shift)
    end
  end
  
  def empty?
    return !@cards.any?
  end

end

Now let’s generate the two starting decks (this is the equivalent of the C snippet above. It’s not straightforward, but I find it way more readable written this way.)

def create_decks
  all_cards = ((2..A).to_a).product(SUITS).map { |x| Card.new(*x) }.shuffle
  return [all_cards[0..(all_cards.count/2 - 1)], all_cards[(all_cards.count/2)..all_cards.count]].map { |x| Deck.new(x) }
end

And now the game logic. If one of the two players can’t draw, he or she loses. If the two players draw cards with different ranks, the winning player is the one who drew the card with the highest rank. If the ranks are equal, then we get into a war. Let’s wrap this piece of logic like so:

def determine_outcome(card1, card2)
  return @deck2 unless card1 #if player 1 can't draw player 2 wins 
  return @deck1 unless card2 #and vice versa
  return war if(card1.rank == card2.rank) 
  return card1.rank > card2.rank ? @deck1 : @deck2
end

Where do card1 and card2 come from? We drew them from the respective player’s deck. The cards go on the table (here represented by the @stack), and the winner takes all the cards after resolution.

def combat
  @stack << @deck1.draw
  @stack << @deck2.draw	
  winner = determine_outcome(@stack[-2], @stack[-1])	
  winner.collect(@stack)	
  return winner
end

Note that, since a war might have happened, there might be more than just the two cards added here in the @stack.
Let’s now see how #war is implemented:

def war
  @stack << @deck1.draw #facedown
  @stack << @deck1.draw
  @stack << @deck2.draw #facedown
  @stack << @deck2.draw
  return determine_outcome(@stack[-3], @stack[-1])
end

We add four cards in total to the stack: first, the first player draws a card, face down. This card is not used at all in the game, except for beling “pillaged” by the winning player. Then the first player draws another card, this one face up – this is the one that will be used for the comparison. The second player does the same. Then we pass the topmost and the third from top card on the @stack (table) to the comparison function – those are the cards played face up.

The game loop goes like this:

def play
  turns = 0
  while [@deck1, @deck2].all? { |x| !x.empty? }
    winner = combat	  
    turns += 1
  end
  print "TURNS : #{turns}\n"
  print "WINNER : player#{winner == @deck1 ? 1 : 2}\n"
end

So, we count the turns passed and we keep drawing until one of the decks is empty. The winner is the last player winning a “fight”.

You can find the complete listing as a gist here. Note that the program will sometime go into an infinite loop – that’s not a bug, it’s actually likely that the game itself as it’s stated is undecisive, and the two player keep drawing forever without having a winner!

Smeed’s Law for programming – an explanation

I’ve come across an interesting blog post a while ago – it was about Smeed’s law and how it relates to software.

Basically, the blog authors said that the number of bugs in a system grows sublinearly with the size of the system itself. There’s no proof for this but it’s the same conclusion I’ve reached with the experience I’ve accumulated so far. This is my explanation for the phenomenon:

Say you have a small software system – for a viable example, think about a prototype, or a shell script you made to take care of trivial stuff. It is very likely that most, if not all, of its parts are not set in stone: if you ever need to add a new feature or to change the behavior of an existing one you will likely have to modify a high percentage of the existing code.

Yep, I suck hard at photoshop

Now think about a bigger system – it might be the prototype from the previous example that now has grown to a complete product. You need to add a feature to that system. If you’ve done things the right way, it’s very unlikely that you will have to modify big parts of the system: chance is, your software’s internals will have grown some sort of API, internal DSL, call it what you want, so all you need to to is either to extend or integrate with it. Also, with time, the bugs in your system’s core will be likely found and eradicated.

Yep, I suck hard at photoshop

Supposing that if you don’t touch it, it won’t break, the part of your system prone to bugs will be the “surface” (2πx), which grows slower than the total area (πx²).

[rant] C# KeyValuePair.Value = (?)

(A couple of years ago I’d be happily coding around the issue at the moment but you know, Ruby makes you a spoiled bastard: my tolerance level for language WTFs has become zero, so I’m here ranting about this)

So I’ve got my nice ICollections and I’m merrily passing them around and binding them to WPF ListBoxes’ ItemSource and stuff and one of the ICollections happens to be an IDictionary. “No worries”, i thought, “It’s still an ICollection so i don’t see the problem” *type type ItemsSource=”{Binding Path=MyDictionary}” type type*. An F5 later this nice RuntimeException pats me on the back:

A TwoWay or OneWayToSource binding cannot work on the read-only property 'Value' of type 'System.Collections.Generic.KeyValuePair`2

Really. You’ve gotta be shitting me. I mean: what happened is that I’m binding the Value property of each element to an editable property and the guys who designed the KeyValuePair class thought it was a good idea to make its Value property readonly. And it’s not over: if you try to inherit KeyValuePair to fix this WTF yourself you’ll find out that the class is Sealed. I am very aware that writing your personal framework class to save yourself some jumping through hoops is generally a Bad Idea but I feel that if I want to I should definitely be allowed to do that.

Is there a vaild reason I don’t know about that justifies this? If so, please let me know!

Unit testing and API design

I have encountered the following situation more than once while working on freightrain: suppose you have a feature in mind, like being able to declare regions (which are other viewmodels, constructed dynamically and plugged into the parent viewmodel’s view accordingly) inside your viewmodel just like this:

class MainViewModel < FreightViewModel

  region :list #:viewmodel defaults to :list
  region :detail, :viewmodel => :customer_detail

end

This has been implemented using a couple of dirty tricks and, of course, it’s all properly tested. The thing is that the tests have been written after the implementation, in a completely separated coding session.

Mind that I am not a very big fan of test driven development: more often than not, especially when the customer is neither trained nor willing to acknowledge the extra effort and the improved quality that comes with it, the costs of test first approach outweigh the benefits it generates. In this case, though, things are different: quality is crucial and I am more than happy to spend time making things better.

Still, I wasn’t really comfortable with writing the test before the actual code. I think that’s because I had a very clear design in mind: testing would just have made the code more complicated than it needs to be. On the downside, the tests written for that piece of code look nothing like the kind of tests that you usually get when doing things TDD style.

What I think I learned from the experience is:

  • While TDD generally helps your design, there are some cases where it gets you to a second best. If you are extremely sure that your design idea is sound then you should abandon testing, do some cowboy coding and when after you’re satisfied with results look back and test everything. The obvious trap is to ditch testing indefinitely: don’t do that.
  • Application design is very different from API design and you have to act (and test) accordingly. Testing the how doesn’t feel that wrong at this level.
  • Sometimes it’s easier to solve a problem with an if or two than to rearrange things: it’s a bad idea and you will see it by the time you test. While ifs are tolerable at the application level they’re a real pain when working at a lower level, and the better the surrounding design the more they hurt. Don’t ignore the warnings.

Horizontal vs. vertical complexity

If i were to choose a principle that summarizes what’s behind a good design, that would absolutely be KISS : as the wise once said nobody is really up to the challenge of being a programmer. Simplicity often means humbleness, which in turn shows that the author has already learned his lesson.
That said, complexity is unavoidable. Code itself is complexity: no lines of code is always the most elegant solution but, zen value put aside, it accomplishes little. We have to deal with some amount of complexity no matter what, so i think it is better to know who your enemy is than to bury your head in the sand ( even if that’s really agile 😉 ).
Let’s take a look at the following snippet :

Now the car must be modified: it shouldn’t be able to move if the engine is not ignited. What should we do to implement this change in behavior?
Horizontal complexity

An if in the right place and voilà, the job is done. It’s the kind of change that TDD (and, by proxy, YAGNI) often brings to: the simplest thing that can possibly work, which is also very often the best thing you can do. It’s horizontal because it doesn’t add layers to your design: an atomic change is most likely to involve just one method or, at most, one class. It’s almost harmless when taken in small quantities but, when misused, can turn really, really bad.
I believe that the real problem about ifs (and conditional statements as a whole) is that they’re too easy. Providing such an easy way to fork the world in two at the language level is like putting RPGs for sale at the grocery store – no matter what’s your level of trust in people’s reasoning, somebody’s gonna get hurt… heck, there’s a whole movement out there trying to put them down.
Vertical complexity

Two new classes and constructor logic: that’s the price you pay so you don’t have to put one of that nasty ifs into your pristine method. It also hides some of the code away from sight: looking at the method only is no longer sufficient to understand its behavior. It’s vertical because the change in your code will be likely to be small in each single part but distributed in various layers.
If you write one if too much you ‘re shooting yourself in the foot; if you do this the wrong way you ‘re blowing your whole leg off.
Overengineering is cheap and often mistaken as quality. The damage done, which often presents itself in the form of Yet Another Crappy Framework destined for internal use, is massive if measures are not taken early so i think it’s a really good idea to stop coding if you don’t know what you’re doing, like when:

  • You just finished reading a certain book which was totally sweet and you can’t wait to see memento in action. On the invoices module.
  • You had a genius idea and you absolutely must put it in your code so everybody knows how freakin’ smart you are.
  • You start to wonder how cool would that be to have all that nasty business logic in a XML file so the customer can edit it himself

In the end…
Which one is better? That depends on you and on the situation: if the code you’re writing will be not be seen by human eyes after it is deployed then i think design and quality are not that important. If you know from the start your code will be mantained (which is pretty much always) it might be a good idea to add some structure (just some) even if the task to accomplish is simple. But if you have no clue please be a good boy, stop coding that CommonMethods class and ask for guidance 🙂

Unit testing with ruby (part 3)

Here follows a dummy controller scenario :

While testing this method is certainly possible, given that both @view and @service are injected at some point before the callback is fired, tests are not going to be lean :

Mock objects are a necessary evil: when there’s no output to check and no clean way to access the modified state you can check for the correct calls to be made on your mocks. Sure, it looks better than no testing at all, but the price to pay is pretty high:

  • Verifying expectations means testing how and not what, which is what you really care about.
  • The tests become much less valuable since they are almost useless as documentation: it takes much less to go straight into the code than to understand what’s going on from reading an integration test.
  • The majority of the test code will be about setting up the environment. In the example the only 2 lines we care about are the one where the expectation is set and the last one, the actual method call on the controller. All the remaining code is just to allow the method to execute.
  • By the fact that you’re testing how mocking basically means duplication of your under-test logic. Adding insult to injury it also makes your tests extremely frail, because even a single change in your logic will reflect into lot of broken tests due to setups not working anymore.

When mocking becomes a source of too much hassle it’s often useful to stop testing and reconsider the code under test: there’s a good chance something ‘s wrong with the underlying design, much likely too much work is done by a single actor, usually the controller (or presenter, viewmodel, you pick it). For instance, assuming that the view mechanics are a given and cannot be modified, the example code would be a little better if refactored to be like this:

Controller methods should be a maximum of three line long, with no ifs. No kidding! I also drop the testing completely on controllers if i can get methods that simple: they add no value and are a pain to keep green, especially on the first stages of development.
In the end i think it’s important to remember that mocking (and unit testing, agile and what else) is just a tool and by the moment it gets in your way you should carefully reconsider what the benefits are: methodology is always out there looking for a chance to strike, don’t let your guard off 🙂

Color scheme designer

I’m an engineer: I can see up to 16 colors and I normally use 4 plus black and white, I’ve got a shortcut for terminal, I use that often and come on, what the f*ck is MistyRose supposed to be.  Still, or maybe especially for those reasons, I found this to be very interesting and i suggest you to give it a look: it is for me what VBA macros are to the average programming noob 🙂