Blog@rtens.orghttps://blog.rtens.org/2020-11-10T00:00:00+01:00Reaching your Goals with Cybernetics2020-11-10T00:00:00+01:002020-11-10T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2020-11-10:/reaching-your-goals-with-cybernetics.html<p><strong>I've recently been thinking about a lot about how to set, track and reach goals. Privately, as well as professionally. And I wanted to share a couple of thoughts, which just happened to come out in dialogue form. So here we go.</strong></p>
<p>What's your goal?</p>
<p><em>I want to go running …</em></p><p><strong>I've recently been thinking about a lot about how to set, track and reach goals. Privately, as well as professionally. And I wanted to share a couple of thoughts, which just happened to come out in dialogue form. So here we go.</strong></p>
<p>What's your goal?</p>
<p><em>I want to go running more often.</em></p>
<p>Why do you want to go running more often?</p>
<p><em>I want to be a better runner.</em></p>
<p>Why do you want to be a better runner?</p>
<p><em>So I can run a Marathon.</em></p>
<p>Why do you want to run a Marathon?</p>
<p><em>Because it would be a great achievement that I can look back to for the rest of my life. I will be able to tell my children and grandchildren about it.</em></p>
<p>Sound like running a Marathon is your real goal.</p>
<p><em>Isn't that too big? They always say you should start small.</em></p>
<p>Yes, start small but dream big. And telling your grandchildren about your achievement sounds like a wonderful dream.</p>
<p><em>True. I can already picture it. All of us sitting around a fire. Their eyes lighting up as I tell the story.</em></p>
<p>Perfect. This vision will be your motivation.</p>
<p><em>And how do I get there?</em></p>
<p>First you need to know where you're going. How would you know that you've reached your goal?</p>
<p><em>I would remember having run a Marathon.</em></p>
<p>Sure. But would there anything objectively different?</p>
<p><em>There would be a medal hanging on my wall over there.</em></p>
<p>Then that's gonna be your indicator that you have reached your goal?</p>
<p><em>Why do I need that?</em></p>
<p>Because "running a Marathon" could mean a lot of things. It could be that you just want to run 42km. But you want to complete an official race and get a medal for it. That's an important difference. By defining an objective indicator of whether you have reached your goal, we get the same idea of what the goal means and I can better help you reaching it.</p>
<p><em>You want to help me?</em></p>
<p>Yes! By showing you an goal-reaching method inspired by cybernetics.</p>
<p><em>Cyber-what? Not sure if that's right for me. I'm not into computer stuff.</em></p>
<p>Cybernetics is the science of controlling complex systems. It stems from the Greek word that means "to steer, navigate, or govern". It looks like this:</p>
<p><img alt="the cybernetic loop" src="/img/cybernetic_loop.jpg"></p>
<p>There is <strong>You</strong> and the <strong>World</strong>. And here is your <strong>Goal</strong>. To reach it you must perform some <strong>Actions</strong> that change the World into one where there is a medal hanging on that wall. That's the cybernetic loop. Perform some Action, check if you have reached your Goal, perform another Action until you reached it.</p>
<p><em>That's not at all helpful.</em></p>
<p>Why not?</p>
<p><em>Because I don't need to look at my wall to know if I have run a Marathon and it doesn't tell me anything about what Actions I need to take.</em></p>
<p>That's right. But it will tell you if your Actions were successful.</p>
<p><em>But only after I have already achieved my Goal.</em></p>
<p>Exactly. And for some goals that would be enough. For small ones for example or for goals that you have already reached.</p>
<p><em>If I've already reached it, it's not a goal.</em></p>
<p>Why not? It's still a place where you want to be. And defining how to tell if you're still there is useful if you want to make sure you don't drift away.</p>
<p><em>I see. But my goal is not small and I definitely haven't reached it yet.</em></p>
<p>True. To reach it, you need to make sure you are constantly moving towards it. How could you tell if you are making progress?</p>
<p><em>If I go running every week.</em></p>
<p>How does that indicate your progress?</p>
<p><em>The more I run, the better a runner I will become.</em></p>
<p>And how much do you need to run to be able to run a Marathon?</p>
<p><em>I don't know.</em></p>
<p>On the day of the race, how will you know if you've run often enough?</p>
<p><em>Hmm. If I can run 42km in under 4 hours.</em></p>
<p>So then the further you can run in 4 hours, the closer you will be to running a Marathon?</p>
<p><em>Yes. But why can't I just count how often I go running? I know I have to do that.</em></p>
<p>Going running every so often will probably bring you closer to running a Marathon. But we don't know how much closer. We can only guess. It's a proxy. Like the gas meter in your car. It shows that you're probably driving, but not how fast or in which direction.</p>
<p><em>But it's much less work to count my runs per week than going for a 4h run just to see how far I get.</em></p>
<p>You're right. It is much less work. That's why we will use it as well to estimate your progress. But we need to remember that it's not the real deal.</p>
<p><em>I understand. What about the other things?</em></p>
<p>What other things?</p>
<p><em>Like registering for the race, buying gear, organizing transport and accomondation. That's all things I need to do so they also show that I'm making progress.</em></p>
<p>That's true. But they are even less likely to indicate real progress. So I wouldn't make them part of the Goal, and instead part of the Actions.</p>
<p><em>But doesn't every Action I take bring me closer to the Goal? That's why I'm doing them right?</em></p>
<p>Yes. But using them to measure your progress would follow a circular logic. You would complete these tasks, to get closer to your goal. But if measure your progress by how many tasks you've completed you don't gain any new information. Instead, we're gonna treat each action as an hypothesis and use our indicators to proof that the action helped with our progress.</p>
<p><em>So I can't even use the tasks as a proxy - like the number of times I go running?</em></p>
<p>We could use it as a proxy. But since we have a good, albeit expensive way of measuring your progress and already a cheaper proxy to estimate it, including these tasks would at best not help much and at worst give you a false sense of progress.</p>
<p><em>I think I understand. The tasks will bring me closer to my goal. But they don't prove that I am making progress. And maybe I do a race in my own city and don't even need transport or accomondation.</em></p>
<p>Yeah, who knows.</p>
<p><em>Is that all?</em></p>
<p>Not quite. We now have a definition of your goal. You have a vision that motivates you, and a way to compare it with the World. You can tell if you've reached it, and even how my progress you're making. All the parts are there but something is missing. </p>
<p><em>Yeah. I need to take Action and actually go through the loop.</em></p>
<p>Yes. And not only once. Consistently.</p>
<p><em>Oooh. I'm not good at consistency.</em></p>
<p>Nobody is. That's why I'll be your goal buddy.</p>
<p><em>What's that?</em></p>
<p>It's someone to measure your progress for.</p>
<p>Someone to celebrate your wins with.</p>
<p>Someone to share your struggles with.</p>
<p>And someone who holds you accountable for your plans.</p>
<p><em>Sounds good. How about we do that every second week?</em></p>
<p>Done. I'm already looking forward to seeing that medal on your wall.</p>
<p><em>Me too.</em></p>Bhutan Last Part2018-05-06T00:00:00+02:002018-05-06T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2018-05-06:/bhutan-last-part.html<p>It's been almost three years now since I returned from my visit to the Himalayas. The whole time I wanted to finish this series, write about the rest of my time there. But as so often, something got in the way.</p>
<p>So apologies for mostly describing pictures now owed to …</p><p>It's been almost three years now since I returned from my visit to the Himalayas. The whole time I wanted to finish this series, write about the rest of my time there. But as so often, something got in the way.</p>
<p>So apologies for mostly describing pictures now owed to my very sparse memory.</p>
<h2>Puppets and Archers</h2>
<p>A friend took me to Garizompa near Thimphu where once a year, where we waited in line with hundreds of people to stick money into the dresses of full-sized puppets of important figures, including the currently residing king.</p>
<p>It was a whole festival with music and dancing and food but these puppets were the main thing.</p>
<p><img alt="Line outside Garizompa" src="/img/bhutan/20160401_162543.jpg">
<img alt="Puppet of the King" src="/img/bhutan/20160401_171458.jpg"></p>
<p>Some day I heard commotion from the arching ground that I passed frequently and realized I haven't watched a single arching competition - Bhutan's national sport - so I went in. I was surprised by how far away the targe were. A 1x1m wooden slate in a 200-300 meters distance. And the opposing team was dancing around it only to behind cover if the arrow looked like it's getting close - apparently to distract the archer.</p>
<p>And of course every hit was celebrated by singing and dancing.</p>
<p><img alt="arching competition" src="/img/bhutan/20160411_111537.jpg">
<img alt="team of archers" src="/img/bhutan/20160411_115453.jpg"></p>
<h2>Hikes</h2>
<p>After a long cold winter, the hiking season finally started for me and I manage to do 3 multi-day hikes (if you count 2 as "multi").</p>
<h3>Druk Path</h3>
<p>The first one was with three Bhutanese friends along the "Druk Path" from Thimphu to Paro.</p>
<p>It started on a beautiful spring day.</p>
<p><img alt="start off druk path" src="/img/bhutan/20160430_113024.jpg">
<img alt="first break" src="/img/bhutan/20160430_115613.jpg">
<img alt="view at first break" src="/img/bhutan/20160430_120137.jpg">
<img alt="up in the mountains" src="/img/bhutan/20160430_151255.jpg"></p>
<p>We found a nice place to pitch our tents near a lake. Just as we were done, we heard the first thunder. Luckily, we were near a cliff which we thought might shield us from lightning so we moved the tents as close to it as we could. As we cooked our first dinner in the mountains, it got dark enough to see the lightning. We started counting the seconds. Still over 30 between the flash and the roar. Nothing to worry about.</p>
<p>It also started to get colder. To cold for me to sleep alone in my tent, so I squeezed in with the other three.</p>
<p>The thunder was approaching now. 10 seconds. Then 5. At some point it was right above us. Nobody spoke a word. We all counted in silence. I only stopped picturing our demise when I reached "10" again. What a night.</p>
<p><img alt="the next morning" src="/img/bhutan/20160501_061910.jpg">
<img alt="frosty mountains" src="/img/bhutan/20160501_090812.jpg"></p>
<p>And what a morning! We were completely snowed in. And as we marched on, it continued snowing the whole day with only occasional breaks in the clouds.</p>
<p><img alt="the clouds clear up a bit" src="/img/bhutan/20160501_151716.jpg"></p>
<p>After 13 hours of hiking, we finally reached our second camping spot, which featured a natural shelter to sit and cook under without being constantly snowed on.</p>
<p><img alt="second camping spot" src="/img/bhutan/20160501_174917.jpg">
<img alt="the second morning" src="/img/bhutan/20160502_054823.jpg"></p>
<p>On our final stretch, we finally got some more sun and also a little friend who followed us. Every group we met going in the other direction was asking us, where our horses are. Turns out it's unusual to hike through the Bhutanese mountains with only what you can carry on your back. But we made it.</p>
<p><img alt="finally the sun" src="/img/bhutan/20160502_085820.jpg">
<img alt="popcorn up high" src="/img/bhutan/20160502_132515.jpg"></p>
<h3>Dagala</h3>
<p>Richer for the experience, I started planning the next hike. It was actually the plan of an Indian girl I met on a day hike, who had a friend visiting - a real nature guy according to her.</p>
<p><img alt="planning over cold brew" src="/img/bhutan/20160503_115329.jpg"></p>
<p>I met him in the Ambient Cafe and where we waited for our guide. Since there are no hiking maps and most trails are pretty lonely (Druk Path being the big exception), we figured better to have somebody with us who knows the way.</p>
<p>With him, we discussed possible tracks, dates and transportation. At some point he asked "How many horses do you have?". We had none. "Then how are you gonna carry the rice cooker?" he asked visibly confused. We didn't intend to bring one. "Then how are you gonna cook the rice?" he wondered in disbelief. We told him we didn't plan to eat rice. "Then I'm not coming."</p>
<p>That's how we lost our guide. We called around to see if anybody else would be willing to come with us. But from everyone we heard the same "No horses? No rice? No way!"</p>
<p>We decided to still give it a try. We had all the food and equipment already anyways. Worst case, we turn around and trace back our GPS track. </p>
<p>A couple of days later, a cab driver dropped us of at the beginning of a five day track to Dagala.</p>
<p><img alt="waiting for the cab" src="/img/bhutan/20160515_175334.jpg">
<img alt="first campsite" src="/img/bhutan/20160512_161117.jpg"></p>
<p>And as soon as we started walking, the rain started pouring and forced out to stop early at the first flat patch of mountain we found after a couple of hours.</p>
<p>We countinued the next day through rain and clouds until it got so foggy that we couldn't see the path anymore.</p>
<p><img alt="into the unknown" src="/img/bhutan/20160513_092651.jpg">
<img alt="foggy mountains" src="/img/bhutan/20160513_094116.jpg">
<img alt="lunch break" src="/img/bhutan/20160513_144036.jpg"></p>
<p>The next morning we dicovered that we were in a beatiful valley and we even had a couple of hours of sun to enjoy it. For example with an early morning swim under a waterfall.</p>
<p>Bit since we weren't sure where the path continued, were exhausted by two days of constant rain and it didn't look like the weather was improving, we decided to stay in the valley for a day, have a nice walk around, and turn back the next day.</p>
<p>We even found a hut.</p>
<p><img alt="a bit of early sun" src="/img/bhutan/20160514_062216.jpg">
<img alt="clouds coming in" src="/img/bhutan/20160514_083533.jpg">
<img alt="found shelter" src="/img/bhutan/20160514_095626.jpg">
<img alt="foggy tea" src="/img/bhutan/20160514_163339.jpg">
<img alt="turning back" src="/img/bhutan/20160515_103114.jpg"></p>
<h3>Phajoding to Buddha Point</h3>
<p>After we dried of a bit, we decided to use our left over food and gas and go for a smaller hike. Just up to the Phajoding - the monastery just about Thimphu - and back down over Buddha Dordenma the next day.</p>
<p>Nothing special except for the spectacular view from Phajoding. And we even made pancakes. Turns out that's a great way to make sure you use all of your gas.</p>
<p><img alt="night view" src="/img/bhutan/20160521_195240.jpg">
<img alt="morning view" src="/img/bhutan/20160522_054840.jpg">
<img alt="clouds over Thimphu" src="/img/bhutan/20160522_062311.jpg">
<img alt="view from the tent" src="/img/bhutan/20160522_065807.jpg">
<img alt="baking pancakes" src="/img/bhutan/20160522_080122.jpg">
<img alt="running from the rain" src="/img/bhutan/20160522_134454.jpg">
<img alt="getting caught up by the rain" src="/img/bhutan/20160522_135530.jpg"></p>
<h2>Projects</h2>
<h3>movies.bt</h3>
<p>Apart from hiking, I also helped to build <a href="https://www.movies.bt/">movies.bt</a> - the Bhutanese movie database. I am surprised to see that as of February 2020, the website is still online and has even expanded quite a bit.</p>
<p>Here is one of my teammates. </p>
<p><img alt="my workplace" src="/img/bhutan/20160617_123510.jpg"></p>
<h3>Groupcash</h3>
<p>I also became fascinated by the concept of complementary currency and started <a href="http://groupcash.rtens.org/">groupcash</a>. Looking for possible applications, my friend from the Druk Path managed to arrange a pilot project with his employer - who happened to be the Royal Monetary Authority of Bhutan aka the national bank.</p>
<p><img alt="presentation at the national bank" src="/img/bhutan/20160525_153940.jpg"></p>
<p>Every year, the RMA's Social Club participates in the national Tree Planting Day and this year every participant got a digital certificate, cryptographically signed by the national bank.</p>
<p>Since I left a month later, nothing came out of it of course. But I got a whole day of tree planting out of it and made loads of new friends.</p>
<p><img alt="on our way to plant trees" src="/img/bhutan/20160602_085813.jpg">
<img alt="RMA social club" src="/img/bhutan/20160602_093241.jpg">
<img alt="hard at work" src="/img/bhutan/20160602_095344.jpg">
<img alt="baby trees" src="/img/bhutan/20160602_101224.jpg">
<img alt="the whole crew" src="/img/bhutan/20160602_120003.jpg"></p>
<h3>Startup Weekends</h3>
<p>And just to round things of, I ended my Bhutan journey like I started with, with a Startup Weekend. I'm still a little bit proud that this time our project - a peer-to-peer bike rental platform - even had one whole paying customer.</p>
<p><img alt="rent-a-bike" src="/img/bhutan/20160605_190014.jpg"></p>
<h2>My Final Weeks</h2>
<p>My last weeks in Bhutan I spent doing all the things that I enjoyed the most. Exploring the areas around Thimphu, spending time with my niece, and supporting Happy Chips.</p>
<p><img alt="Dzong of Thimphu" src="/img/bhutan/20160530_161402.jpg">
<img alt="on the way to paro" src="/img/bhutan/20160608_131157.jpg">
<img alt="Bhutan life" src="/img/bhutan/20160610_112818.jpg">
<img alt="big bug" src="/img/bhutan/20160617_192636.jpg">
<img alt="happy chips campaign" src="/img/bhutan/20160619_161128.jpg"></p>
<h2>Monk in Tango</h2>
<p>After months of working on it, my sister actually managed through a friend to arrange for me the possibility of spending two weeks in a Buddhist monastery. It was a true honor.</p>
<p>I was welcomed warmly, got my own room, and was able to participate in all activities (as far as my abilities allowed). My days looked somewhat like this: I got up with the daily gong at five, spent one hour chanting and meditating, had rice for breakfast, spent a couple of hours reading, walking or meditating, had rice for lunch, gave English lessons, meditated some more, had rice for dinner, and went to bed with the setting sun.</p>
<p>Since I'm worried that I'll never publish this otherwise, I'll let the pictures speak for themselves.</p>
<p><img alt="watching football" src="/img/bhutan/20160621_221549.jpg">
<img alt="going to class" src="/img/bhutan/20160622_090343.jpg">
<img alt="sacred bridge" src="/img/bhutan/20160622_094746.jpg">
<img alt="shoes outside praying hall" src="/img/bhutan/20160622_161914.jpg">
<img alt="me in monk robes" src="/img/bhutan/20160623_105037.jpg">
<img alt="lunch time" src="/img/bhutan/20160623_120557.jpg">
<img alt="computer class" src="/img/bhutan/20160624_191238.jpg">
<img alt="paying hall" src="/img/bhutan/20160625_193938.jpg">
<img alt="my favourite spot" src="/img/bhutan/20160626_092540.jpg">
<img alt="the monastery" src="/img/bhutan/20160626_163027.jpg">
<img alt="making rice statues" src="/img/bhutan/20160628_085227.jpg">
<img alt="tango" src="/img/bhutan/20160628_091739.jpg">
<img alt="carrying up construction material" src="/img/bhutan/20160628_092156.jpg">
<img alt="preparing the festival" src="/img/bhutan/20160628_122435.jpg">
<img alt="my room" src="/img/bhutan/20160630_095131.jpg">
<img alt="my friends" src="/img/bhutan/20160630_105051.jpg">
<img alt="festival ornament from rice dough" src="/img/bhutan/20160630_132019.jpg">
<img alt="posing" src="/img/bhutan/20160630_132114.jpg"></p>
<h2>Goodbye Bhutan</h2>
<p>After Tango I only had about a week left. So I had one last good-bye party, gave Jimmey a final rub, and headed to Paro.</p>
<p><img alt="goodbye party" src="/img/bhutan/20160702_203859_LLS.jpg">
<img alt="goodbye to jimmy" src="/img/bhutan/20160704_120627.jpg">
<img alt="master smith" src="/img/bhutan/20160705_150144.jpg">
<img alt="last morning in Bhutan" src="/img/bhutan/20160706_062755.jpg"></p>
<p>An amazing time, that I wish I would have written more about when it wasn't years ago. But I hope these words and pictures give somewhat an impression of my time there.</p>A Time System for the Space Age2018-05-03T00:00:00+02:002018-05-03T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2018-05-03:/a-time-system-for-the-space-age.html<p>I used last Christmas break to watch "The Expanse" which quickly became my favorite SciFi series with its incredibly realistic and inspirational vision of a humanity that has colonized the solar system. And it was one sentence in this show that struck an unexpected chord with me. It was a …</p><p>I used last Christmas break to watch "The Expanse" which quickly became my favorite SciFi series with its incredibly realistic and inspirational vision of a humanity that has colonized the solar system. And it was one sentence in this show that struck an unexpected chord with me. It was a comment about how - even centuries after populating Mars and the asteroid belt - people still used earth-based units to measure time such as days, months and years. As probably almost <a href="https://zachholman.com/talk/utc-is-enough-for-everyone-right">every software developer</a>, I struggled more than once with the convoluted dominant time system of this planet, and this comment got me once again thinking about what an alternative might look like.</p>
<p>The result of this holiday pondering is <em><a href="http://time.rtens.org/">Reference Time</a></em>, a time system designed for the Space Age. A time system for a fundamentally relative universe, and a time system for humans, using simple and regular units. Reference Time is always defined relative to a frame of reference and simply counts seconds passing in this frame since an arbitrary zero point, grouped in decimal units that are meaningful to people.</p>
<h2>Design Goals</h2>
<blockquote>
<p>"We have a choice: do we actually think, that the sun, the stars and the moon are important to our lives, or do we think that our lives should be controlled by intervals?" - <a href="http://www.bbc.co.uk/programmes/b01dvw6t">Kristen Lippincott</a></p>
</blockquote>
<p>As long as we live only on this one planet, the movement of the sun, the stars and the moon are probably still important to our lives. But what time system would make sense for a civilization that is not bound to a single planet anymore? What if the sun, earth and the moon are too far away to guide us? What if we start living in completely artificial environments were it makes much more sense to let intervals control our lives? Intervals that we choose. What could time for a space faring civilization look like?</p>
<h3>Relativity</h3>
<p>Time is relative. And not only in the sense that a second in the supermarket queue appears longer than on the beach, but also in a very physical sense. One of the most important predictions of Einstein's theory of <a href="https://www.youtube.com/playlist?list=PLoaVOjvkzQtyjhV55wZcdicAz5KexgKvm">Special Relativity</a> was that time behaves differently in different frames of reference moving at different speeds, which is most impressively demonstrated by the fact that clocks on GPS satellites shift about <a href="https://en.wikipedia.org/wiki/Global_Positioning_System#Timekeeping">38 microseconds</a> per day compared to clocks on earth. While this time dilation can be calculated precisely for satellites in a known and carefully tracked orbit, it would be very difficult for a large number of vessels zipping through the solar system on unpredictable trajectories. So a space-age time system should incorporate the fact that every interval is always relative to a specific frame of reference, e.g. the surface of a planet, an orbit or a vessel.</p>
<p>Time is personal. While the thought of abolishing all timezones is tempting, it is not compatible with reality where time is all but universal. Space exploration will only increase the number of timezones with different cycle lengths, time dilations and even people living on the same station but in different time zones to provide uninterrupted operations. A universal time system should therefore embrace the fact that everybody is following their own clocks, explicitly state the offset and a frame of reference, and make conversion between them as simple as possible.</p>
<h3>Regularity</h3>
<p>To ease calculations, the time system needs to be as regular as possible. The notation of our current calendars and clocks use decimal place-value numbers but different bases for minutes, hours, days and weeks and even irregular lengths for months and years. And although bases like 12 and 60 make division easier, it comes at the cost of addition and subtraction which in my experience are the much more frequent operations on time. A regular time system should use the same base for all of its units and numbers.</p>
<p>Irregular units make calculations harder, but as long as the exceptions are predictable (e.g. leap years), they're still possible. A time system bound to natural phenomena will also include unpredictable discontinuations (e.g. leap seconds), which in the best case make calculation impossible and in the worst case leads to contradictory results. A continuous time system should avoid cyclic and sporadic exceptions.</p>
<h3>Usability</h3>
<p>Relativity and regularity make a time system easier to use for machines, but it also should be usable for humans. We need to be able to easily speak about time frames that are important to us. For people living in artificial environments, this may be different intervals than the natural cycles we use nowadays. A usable time system should enable precise and efficient communication while avoiding ambiguity.</p>
<h2>Reference Time</h2>
<p>I would like to propose a <em>time system for the space age</em>, which is not bound to the natural cycles of a single planet, but designed for <strong>regularity</strong>, <strong>usability</strong>, and most importantly <strong>relativity</strong>. The relative nature of time means it can only ever be measure relative to a frame of reference. <em>Reference Time</em> counts <strong><a href="https://en.wikipedia.org/wiki/Second">SI seconds</a></strong>, grouped into <strong>decimal units</strong>, relative to a <strong>frame of reference</strong>, that have lapsed since an arbitrary <strong>zero point</strong>.</p>
<p>Instead of insisting on a single, universal time, in <em>Reference Time</em> a point of time is always given in reference to something. Examples are "We'll arrive at 42 Cycles and 21 Turns, Ship-time since mission start" or "The meeting starts at 97 Turns and 5 Moments, Station-time since start of shift" or "I was born at 400 Generations, 46 Rotations and 45 Cycles, Earth-time since start of humanity".</p>
<h3>Units</h3>
<p>Counting seconds makes for a very regular time system, but gets quickly unwieldy. To facilitate machine-to-human and human-to-human communication, seconds are grouped into decimal units. It happens to work out that groups of 100 (and one group of 10) lead to very useful intervals.</p>
<p>Here they are:</p>
<ul>
<li>1 Second is 1 <em>Second</em> - the time between two heart beats of a well-trained person, or the time it takes to say "1 elephant".</li>
<li>100 Seconds are 1 <em>Moment</em> - a little less than 2 minutes and a good unit for business events, e.g. for bus schedules or appointments.</li>
<li>10 Moments are 1 <em>Turn</em> - a little more than a quarter hour and a good unit for social events, e.g. meeting friends or starting dinner. It's also a nice unit for splitting up a working day, e.g. "this is gonna take 5 Turns".</li>
<li>100 Turns is 1 <em>Cycle</em> - a little longer than an Earth day so not really useful on Earth but it might be suitable for sleep cycles in artificial environments.</li>
<li>100 Cycle is 1 <em>Rotation</em> - about a third of a year which seems like a good unit of time to track personal and professional progress or to plan projects, e.g. "Next Rotation I wanna learn piano." </li>
<li>100 Rotations is 1 <em>Generation</em> - with 31.7 years very close to the <a href="https://www.ncbi.nlm.nih.gov/pubmed/10677323">average time between human generations</a> and the largest unit of time in the system, e.g. "the Roman empire fell 47 generations ago".</li>
</ul>
<h3>Zero Points</h3>
<p>Zero points are freely chosen and multiple clocks can be synchronized by broadcasting a reference description along with the number of seconds counted. Alternatively, a zero point can be defined in terms of external events or other time systems. For example "1st of January 1970", "next midnight UTC plus 2 hours", "last high sun in Greenwich", or even "when I got up today".</p>
<p>For an coordinated <a href="http://time.rtens.org/">Earth Reference Time</a> (ERT), we need a widely accepted, precise and continuous time signal. I picked the one emitted by the satellites of the <a href="https://en.wikipedia.org/wiki/Global_Positioning_System#Timekeeping">Global Positioning System</a>, which uses the <a href="https://en.wikipedia.org/wiki/Geoid">Geoid</a> as its frame of reference. Regarding the zero point, I would follow the suggestion of <a href="https://www.youtube.com/watch?v=czgOWmtGVGs">Kurzgesagt</a> and define ERT as GPS + 400 Generations, which puts 0 ERT roughly at the <a href="https://en.wikipedia.org/wiki/History_of_the_world#Rise_of_civilization">start of civilization</a>.</p>
<h2>Other Time Systems</h2>
<p>There are of course many many time systems already out there and you might (rightfully) have the strong desire to point me to <a href="https://xkcd.com/927/">xkcd#927</a> by now. And maybe I simply had too much time on my hand over the holidays but none of the systems I could find meet the stated design goals. Let's have a quick look at some.</p>
<p><strong>Coordinated Universal Time</strong> (<a href="https://en.wikipedia.org/wiki/Coordinated_Universal_Time">UTC</a>) is all but regular or predictable and also does not support different frames of references since time zones are defined by a fixed offset and depend more on arbitrary political decisions than location. A more regular version of UTC is <strong><a href="https://en.wikipedia.org/wiki/Unix_time">Unix time</a></strong> which only counts seconds (skipping leap seconds) which makes it much less usable for humans.</p>
<p>Various <strong><a href="https://en.wikipedia.org/wiki/Decimal_time">decimal time</a></strong> systems tried to improve regularity, usually by dividing an average Earth day repeatedly by ten. These systems inherit all problems of whatever calendar they are bound to, and sacrifice ease of division for only a small facilitation of addition and subtraction. They also usually redefine the length of a "second".</p>
<p>The <strong>International Atomic Time</strong> (<a href="https://en.wikipedia.org/wiki/International_Atomic_Time">TAI</a>) is continuous (by ignoring leap seconds) but apart from that as irregular as UTC. Unless you use a notation like <a href="https://www.tai64.com/">TAI64</a> which is extremely regular by counting only seconds but it still does not support different frames of reference and is unusable to anyone who needs to handle large amounts of seconds or who is not fluent in hexadecimal notation. The time of <strong><a href="https://en.wikipedia.org/wiki/Global_Positioning_System#Timekeeping">GPS</a> satellites</strong> can be derived from TAI, but counts weeks and seconds instead of using the Gregorian calendar. Although this is an improvement over just counting seconds, it still doesn't make it human friendly.</p>
<h2>Reality Check</h2>
<p>So what's this <em>Reference Time</em> actually good for? Probably not much. Living in a natural environment, there is little reason to adopt it. Also, mechanic watches and Gregorian calendars won't disappear anytime soon. But to me it's an idea worth thinking about. As an experiment, I implemented the <a href="http://time.rtens.org/">watch face</a> for Wear OS and started living on my personal reference time which resets to zero every morning when I wake up. Computers make different time zones much more manageable and I rarely have to manually transform one time system into the other, since the current time and the time until my next calendar event are always displayed on my watch. Several weeks into the experiment, I feel like even on Earth, having a time system that is just a little more personal and human-centered does make my day a bit easier and more enjoyable. And it's a nice ice-breaker.</p>Everyone Should be Software Literate2018-04-25T00:00:00+02:002018-04-25T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2018-04-25:/everyone-should-be-software-literate.html<p>The YouTube recommendation algorithm recently put a video titled <a href="https://www.youtube.com/watch?v=EFwa5Owp0-k">"Not Everyone Should Code"</a> on my home screen and I got curious. Mostly concentrating on why everybody should become software literate for the last years, I wanted to know what their arguments against would be.</p>
<p>First off: it's a great video …</p><p>The YouTube recommendation algorithm recently put a video titled <a href="https://www.youtube.com/watch?v=EFwa5Owp0-k">"Not Everyone Should Code"</a> on my home screen and I got curious. Mostly concentrating on why everybody should become software literate for the last years, I wanted to know what their arguments against would be.</p>
<p>First off: it's a great video, well made and I really enjoyed its style. But it should be titled "Not Everyone should become a Professional Programmer", since that's its actual premise. With which I agree.</p>
<blockquote>
<p>"It is just a job, not a basic universal skill."</p>
</blockquote>
<p>I would summarize the author's main argument as "coding isn't for everyone", "people have different talents" and "not everyone should become a surgeon neither".</p>
<blockquote>
<p>"Why is programming treated in a way that surgery isn't? Because we're told it's not just another trait, but an essential skill like reading and writing. And if it is, then it totally should be required in every school. But if not - and I don't think it is - then it's just one, admittedly good, career path of many."</p>
</blockquote>
<p>Unfortunately, the author doesn't talk much about <em>why</em> they don't think programming is an essential skill. This is the only paragraph I could find that related to this statement.</p>
<blockquote>
<p>"Both farmer and maison still need to read and write. But programming can't be such a skill. It's difficult enough that it just doesn't make economic sense for everyone to learn it. Unless or until robots take over everything jobs need [to be] done. More and more will involve computers, but it won't be doctors and teachers programming them."</p>
</blockquote>
<p>So the conclusion is based on the assumption that creating software is difficult and will remain difficult. But this is exactly the problem that me and many other researchers are trying to solve. I strongly believe that we can make creating, sharing, understanding and manipulating software by at least an order of magnitude easier. Many skills, including text literacy and arithmetic were once deemed "too difficult" to be learned by the general public.</p>
<p>The disagreement might also be caused by a different understanding of what "coding", or "programming" is. The author does differentiate between "programming" and "computer science" whereas they equate the former to "being able to write a simple programm" and the later to "solving complex problems with programs" and claims that "learning to code" implies both.</p>
<p>This is the reason why I avoid the term "coding" and also try to avoid "programming" since they are usually associated with typing complicated syntax and professional software development. For me, it's all about being able to express your own ideas in software and being able to understand someone else's ideas expressed in software and manipulate it.</p>
<p>I suspect that the motivation to make this video might come from the authors frustration with many courses and "bootcamps" promising that you can "learn to code in x weeks", implying that you will be a professional software developer upon completion. Combined with high salaries, this indeed might drive people into the field, who might otherwise have fallen for another <em>get rich quick</em> scheme.</p>
<p>But regarding the low salary of other important traits, the author unfortunately assumes that the reverse conclusion is also true, arguing that</p>
<blockquote>
<p>"it would be awesome if teachers were paid more, but one benefit of what we have is that it selects for people passionate about the job, not just after a paycheck."</p>
</blockquote>
<p>which to me seems like an indicator for a lack of empathy.</p>
<p>And lastly, the very end (before the sponsor plug) contains a part that nicely summarized why I watched the video in the first place.</p>
<blockquote>
<p>"If you're already sold on the importance of programming, it's easy to see everything through that lense."</p>
</blockquote>
<p>Which reminded me of how important it is to be aware of <a href="https://en.wikipedia.org/wiki/List_of_cognitive_biases">one's cognitive biases</a>. So thanks for making this video, <a href="https://www.youtube.com/channel/UCgNg3vwj3xt7QOrcIDaHdFg">PolyMatter</a></p>On Principles2017-07-16T00:00:00+02:002017-07-16T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2017-07-16:/on-principles.html<p>In high school, I was oftentimes mocked for caring too much about principles. Saying things like "This is against my principles" or "I'm doing this out of principle" earns you quite bit of ridicule from fellow teenagers. And even today, I still get scoffed at when I'm one of the …</p><p>In high school, I was oftentimes mocked for caring too much about principles. Saying things like "This is against my principles" or "I'm doing this out of principle" earns you quite bit of ridicule from fellow teenagers. And even today, I still get scoffed at when I'm one of the few cyclists in this city that stops at a red light. Out of principle.</p>
<p>So I wasn't too surprised when <a href="http://worrydream.com/">Bret Victor</a>'s talk <a href="https://vimeo.com/36579366"><em>Inventing on Principle</em></a> resonated deeply with me. I'm all about principles. But yet, I never looked for one in my work. Not of the kind that Victor talks about at least. But I got the feeling that there might be one.</p>
<h2>Choices</h2>
<p>How do you live your life? How do you want to live you life? Why did you make the decisions you made? What do you want to stand for as a person? These are not the usual questions that you hear in a talk at a technical conference. But in this talk (transcript <a href="http://blog.ezyang.com/2012/02/transcript-of-inventing-on-principleb/">here</a>), Victor speaks about nothing less than the question of all questions: What do I want to do with my life?</p>
<p>This is already the <a href="http://worrydream.com/ClimateChange/">second time</a> that Victor has deeply inspired me with his words. But I can't remember another presentation that moved as much as this one. He ends it with a truth that is as important and universal as it is simple. It's a liberating realization that yet many people refuse to accept.</p>
<blockquote>
<p>There are many ways to live your life. What's maybe the most important thing you can realize in your life, is that every aspect of your life is a choice. But there are default choices. You can choose to sleepwalk through your life and accept the path that's been laid out for you. You can choose to accept the world as it is. But you don't have to.</p>
</blockquote>
<p>That sounds a lot like the usual "quit your job", "follow your dreams" and "listen to your heart" kind of talks. But Victor goes down another path. Instead of letting your economic interests or your heart guide your decisions, he suggests to discover a <em>principle</em>. In his words:</p>
<blockquote>
<p>If there is something in the world you feel is a wrong and you have a vision for what a better world could be, you can find your guiding principle. And you can fight for a cause. So after this talk, I'd like you to take a little time and think about what matters to you. What you believe in. And what you might fight for.</p>
</blockquote>
<h2>The Pain</h2>
<p>I followed his advice and looked for things in the world that I consider "a wrong" and where I see a moral obligation to change them. I started to take better notice of all the little things that hurt me to watch. Just like it hurts Victor when he sees an idea die or like it hurts Larry Tesler when he sees someone stuck in a mode.</p>
<p>One thing that came into my mind immediately was the sting I feel when I see a screenshot of text on Twitter. That hurts. Or pictures of graphs on websites. That hurts as well. Also the fact that I have to copy a picture in order to share it with a friend or rely on a third party service to share my files or do simple surveys. I even need a third party just to get a reminder about emails I haven't gotten a reply to yet. </p>
<p>I feel pain when I think about how an international consortium decides what pictograms I can text to my mom. Or about how much work goes into making a website work on all browsers and platforms. Every time I see someone struggle with file formats - be it video, graphics or formatted text - it hurts. And it hurts when I'm forced to export something as PDF. Or when I have to download a CSV from one service just to upload it again to another. Although you could argue that it's quite amazing <em>if</em> that's possible at all. </p>
<p>Because what hurts even more is when my own content is locked away from me. And the worst pain I feel when I read stories about people loosing all their content because Facebook suspended their accounts without giving a proper reason or hearing. It hurts when a million passwords get stolen, and that a lot of them can be used for the email addresses that can reset them, and that that's usually enough to steal an entire identity. I also hate spam.</p>
<p>It hurts that I have to download an app on my phone just to do one simple thing. And that I have to uninstall another app first because I'm running out of space. And that I have to give it irrevocable blanket permissions to access my files or camera. It hurts that I have 8 different messaging apps installed in order to talk to people. And lastly, I cringe every time I have to manually restart my WiFi when the connection fails for no obvious reason.</p>
<h2>The Vision</h2>
<p>I couldn't really infer a principle from these pain points. And I don't enjoy focusing too much on negatives anyway. So I also looked at my own work and at things that have inspired me for some more clues.</p>
<p>Bret Victor is certainly high up on my personal list of inspirations. Especially his interactive essays and demos of highly interactive authoring tools. The most interactive authoring tools I have at my own disposal is certainly Squeak Smalltalk. Everything about it is highly inspirational, along with pretty much <a href="https://www.youtube.com/playlist?list=PLwia5ezffHz6zhMc7is7aPGwKsLElPFWU">everything Alan Kay utters</a>. Another thing that comes to mind is Paul Chiusano's take on <a href="http://pchiusano.github.io/2013-05-22/future-of-software.html">The Future of Software</a> and Ted Nelson's ideas about data structures. I'm also very much inspired by the <a href="http://one.laptop.org/">One Laptop Per Child</a> project and how the XO-1 and C.H.I.P. computers let you look under the hood. Or how Richard Pawson's <a href="https://en.wikipedia.org/wiki/Naked_objects">Naked Objects</a> allow the user to directly interact with the domain model.</p>
<p>My own work has lately evolved around Domain-Driven Design, Command/Query Responsibility Segregation, Event Sourcing, Specification by Example (aka Behaviour-Driven Development), Ubiquitous Language and collaborative domain modeling. I built a user <a href="https://github.com/rtens/domin">interface generator</a> that is quite similar to Pawson's approach but is based on commands and queries instead of entities. I used it for a couple of prototypes and it was very helpful with debugging the domain model since it allowed me to give users direct access to the model early on.</p>
<p>And most importantly, last September I defrosted <a href="http://zells.org">zells</a> and since then dedicated as much time as I can afford to it. Zells is a software platform with a minimal programming model. Basically it's a mix of Kay's, Victor's, Nelson's and other ideas. My goal with this project is to enable software literacy by avoiding incidental complications of other programming platforms and thus making creating, understanding, manipulating and sharing software more accessible.</p>
<h2>My Principle</h2>
<p>Looking at my paint points and inspirations, my principle seems to have something to do with how people interact with computers. More specifically, what models they interact with and what lies between them and the model. But how to phrase it? Searching for inspirations, I looked at other people's principles.</p>
<blockquote>
<p>Creators need an immediate connection to what they're creating. - <em>Bret Victor</em></p>
<p>No modes. - <em>Larry Tesler</em></p>
<p>Women should vote. - <em>Elizabeth Cady Stanton</em></p>
<p>Software must be free, as in freedom. - <em>Richard Stallman</em></p>
<p>Enable mankind to solve the world's urgent problems. - <em>Doug Engelbart</em></p>
<p>Amplify human reach and bring new ways of thinking to a faltering civilization that desperately needs it. - <em>Alan Kay</em></p>
</blockquote>
<p>In his presentation, Victor uses Larry Tesler's principle "No modes." as an example to describe what properties a principle should have.</p>
<blockquote>
<p>If you choose to follow a principle, a principle can't just be any old thing you believe in. Larry Tesler['s principle] is a powerful principle because it gave him a new way of seeing the world. It divided the world in right and wrong in a fairly objective way. So, he could look at somebody selecting text and ask: Is this person in a mode? Yes or no? If yes, he had to do something about that.</p>
</blockquote>
<p>So why not do it like Tesler? It seems I have a problem with computer users being unnecessarily separated from the dynamic models they are working with. So my principle could simply be expressed as</p>
<blockquote>
<p>No UI. - <em>Nikolas Martens</em></p>
</blockquote>
<h2>Your Principle</h2>
<p>Since I cannot add anything valuable to to them, I end this bit with Victor's words.</p>
<blockquote>
<p>So, you can choose this life. Or maybe it will end up choosing you. It might not happen right away. It can take time to find a principle because finding a principle is essentially a form of self-discovery, that you're trying to figure out what your life is supposed to be about. What you want to stand for as a person. Took me like a decade. [...] I'm not saying you have to live this way. I'm not saying that you should live this way. What I'm saying is that you can.</p>
</blockquote>DPC 20172017-06-30T00:00:00+02:002017-06-30T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2017-06-30:/dpc-2017.html<p>For my last conference of 2017 I travelled, as for the first of this year, to Amsterday to talk about <a href="http://specificationbyexample.com">Specification by Example</a> (aka Behaviour-Driven Development) and the <em>Dutch PHP Conference</em>. I used to opportunity to revise the presentation and slides which you can find <a href="/res/sbe_presentation_v2.pdf">here</a>.</p>
<p>Update: A video of …</p><p>For my last conference of 2017 I travelled, as for the first of this year, to Amsterday to talk about <a href="http://specificationbyexample.com">Specification by Example</a> (aka Behaviour-Driven Development) and the <em>Dutch PHP Conference</em>. I used to opportunity to revise the presentation and slides which you can find <a href="/res/sbe_presentation_v2.pdf">here</a>.</p>
<p>Update: A video of the talk is now <a href="https://www.youtube.com/watch?v=XaKSrcuEYUw">available on youtube</a>.</p>IPC 20172017-05-30T00:00:00+02:002017-05-30T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2017-05-30:/ipc-2017.html<p>I was very happy to get the opportunity to talk about <strong>Rapid Prototyping with Domain-Driven Design</strong> at the International PHP Conference in Berlin. You can find the revised version of my <a href="/res/rapid_prototyping_with_ddd_v2.pdf">slides here</a>. Unfortunately my agenda didn't allow me to attend many of the sessions but it was great meeting …</p><p>I was very happy to get the opportunity to talk about <strong>Rapid Prototyping with Domain-Driven Design</strong> at the International PHP Conference in Berlin. You can find the revised version of my <a href="/res/rapid_prototyping_with_ddd_v2.pdf">slides here</a>. Unfortunately my agenda didn't allow me to attend many of the sessions but it was great meeting many friends from the PHP community again.</p>
<p>I was even asked to write an article about essential complexity which was <a href="https://phpconference.com/blog/essential-complexity/">published on IPC's blog</a>.</p>
<p>So many thanks to the team for organizing a great conference!</p>GPN 20172017-05-25T00:00:00+02:002017-05-25T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2017-05-25:/gpn-2017.html<p>The <a href="https://entropia.de/GPN17">Gulaschprogrammiernacht</a> (GPN) was my first deliberate journey into the hacker community and I have since been working hard on forgiving myself for not having gone every single year before. It was great fun just randomly talkin to people about their ideas and projects, trying out more VR headsets, playing …</p><p>The <a href="https://entropia.de/GPN17">Gulaschprogrammiernacht</a> (GPN) was my first deliberate journey into the hacker community and I have since been working hard on forgiving myself for not having gone every single year before. It was great fun just randomly talkin to people about their ideas and projects, trying out more VR headsets, playing experimental table top games and it was definitely the first time I drove a Club Mate crate.</p>
<p>I used the opportunity to tell as many people as possible about <a href="http://zells.org">zells</a> and also gave a <a href="/res/dont_learn_coding.pdf">lightning talk</a> about it, which spawned many more interesting conversations. You can <a href="https://media.ccc.de/v/gpn17-8602-lightning_talks_1#t=978">watch the talk here</a>.</p>
<p>Hope I will make it again to Karlsruhe next year.</p>Codemotion Amsterdam 20172017-05-16T00:00:00+02:002017-05-16T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2017-05-16:/codemotion-amsterdam-2017.html<p>My first conference of 2017 brought me to my new favourite city, Amsterdam. There is very litte beating sitting at the canals on a warm May evening with a cold beer and good conversations.</p>
<p>So thanks to Codemotion for yet again organizing an excellent event and giving me the opportunity …</p><p>My first conference of 2017 brought me to my new favourite city, Amsterdam. There is very litte beating sitting at the canals on a warm May evening with a cold beer and good conversations.</p>
<p>So thanks to Codemotion for yet again organizing an excellent event and giving me the opportunity to talk about Template Animation. It was very interesting to explore what has changed since I talked about this topic <a href="http://blog.rtens.org/codemotion-2013.html">four years earlier</a> (almost to the day) at my very first conference, which was also Codemotion, in Berlin.</p>Essential Complexity is Essential2017-05-11T00:00:00+02:002017-05-11T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2017-05-11:/essential-complexity-is-essential.html<p>(This article was featured on the <a href="https://phpconference.com/blog/essential-complexity/">blog of the International PHP Conference</a>)</p>
<p>The premise of my talk "<a href="/res/rapid_prototyping_with_ddd_v2.pdf">Rapid Prototyping with Domain-Driven Design</a>" is that the two greatest foes of every software developer are a) uncertainty and b) complexity. Over the years, we have invented many tools and methods to fight …</p><p>(This article was featured on the <a href="https://phpconference.com/blog/essential-complexity/">blog of the International PHP Conference</a>)</p>
<p>The premise of my talk "<a href="/res/rapid_prototyping_with_ddd_v2.pdf">Rapid Prototyping with Domain-Driven Design</a>" is that the two greatest foes of every software developer are a) uncertainty and b) complexity. Over the years, we have invented many tools and methods to fight them. But eventually we realized that uncertainty cannot be defeated and instead we learned to embrace it with ever shorter feedback cycles, "agile" methods, continuous integration, devops and Test-Driven Development.</p>
<p>But what about complexity? Can it be defeated? We sure are trying. Every other week there is a new programming language claiming to reduce it, every other day a new framework to make storage, networking, rendering or communication easier than ever before.</p>
<p>One could think that if this trend continues, writing software might one day be as easy as 123. But these are all solutions to technical problems and while they receive a lot of attention, I consider them unessential. There are many ways to solve a certain problem with software. Many different languages and frameworks to use. Each with their own benefits but also own drawbacks, like added complexity.</p>
<p>Outside the technology lies the conceptual space of the problem you are trying to solve with your piece of software - the domain. If you are creating a jump-n-run game, your domain includes physics, didactics and game design. If you write a restaurant management system, your domain consists of tables, orders and bills. Whatever kind of software you write, you will have to deal with the domain and its complexity. It cannot be avoided.</p>
<p>This is why in the talk I claim that "complexity is essentially in the domain".</p>
<p>The good news is that we might actually one day defeat unessential complexity. Many people, myself included, are working on it. But the bad news is that even then we will still be stuck with the complexity of the domain, which we cannot reduce without reducing the problem, since it’s part of it.</p>
<p>But it’s really not that bad because without unessential complexity, the difficulty of the solution depends solely on the problem. Easy problems, like organizing your grocery shopping would be trivial to solve. Harder problems, like analyzing your supermarket receipts and calculating your consumption rate of butter, would be only proportionally more difficult, with a smooth learning curve between them.</p>
<p>My personal hope is that it is possible to build a software development tool that avoids all unessential complexities. With such a tool, everybody could solve most of their own problems themselves. It could lead to a general software literacy, enabling people of every trade to take advantage of the full potential of computers, without depending on a tiny fraction of the “elite” to solve their problems for them.</p>
<p>Without technical complexity to conquer, software creators could completely focus on the domain. Instead of battling with encoding and databases, programmers could spend their time on understanding the world and forging their insights into dynamic models.</p>
<p>But we are not quite there yet. The tools we use are still complex enough that they require weeks of training before you can write software that solves even the simplest of your problems, let alone the harder ones. So you don’t need to worry that your knowledge of the newest Javascript framework becomes obsolete soon. Our jobs are safe yet.</p>
<p>We still need professionals for creating and maintaining every tiny bit of software but because engineers have an inclination towards technical problems, we tend to neglect the domain.</p>
<p>If we accept that technical complexity is essentially in the domain, we can start to avoid technical complexity and focus on the essential problem, the domain. This is the premise of Domain-Driven Design.</p>Flaccid Democracy2016-12-18T00:00:00+01:002016-12-18T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2016-12-18:/flaccid-democracy.html<p>I must confess I was never much interested in politics, and therefore very grateful when I found the <a href="https://www.wahl-o-mat.de">Wahl-o-mat</a> which freed me from having to read the party platforms myself. I always viewed <a href="https://www.opendemocracy.net/ourkingdom/hendrik-wagenaar/is-democracy-in-crisis-no-there%e2%80%99s-just-new-type-of-emerging-democracy">non-politic civic participation</a> as the more effective, certainly more efficient way for changing society and have been …</p><p>I must confess I was never much interested in politics, and therefore very grateful when I found the <a href="https://www.wahl-o-mat.de">Wahl-o-mat</a> which freed me from having to read the party platforms myself. I always viewed <a href="https://www.opendemocracy.net/ourkingdom/hendrik-wagenaar/is-democracy-in-crisis-no-there%e2%80%99s-just-new-type-of-emerging-democracy">non-politic civic participation</a> as the more effective, certainly more efficient way for changing society and have been pondering for years how the open market's incentives can be moved towards a more social and sustainable economy. Indeed I always thought of politics to be quite tedious, boring even. I now realized what a luxury that was.</p>
<p>I the world in a crisis? Is democracy in a crisis? It's probably too early to say but it sure looks that way. It seems to be getting from bad to worse to absolute worst. First, the success of right-wing parties in eastern Europe, then the formation and partial success of a new nationalist party in Germany, then Brexit and now Trump.</p>
<p>Why is this happening? I don't know and I haven't seen a satisfying answer yet. But I have a theory.</p>
<h2>Technical Debt</h2>
<p>When I saw what is happening in these countries I experienced a familiar feeling. I was still very much convinced that the system is not to blame. But something went clearly wrong. It was the same feeling that I had when I saw or read about software development teams that were unhappy with "Agile" and are convinced that it "failed" them.</p>
<p>What I saw in these teams was something that Martin Fowler calls <a href="http://martinfowler.com/bliki/FlaccidScrum.html">Flaccid Scrum</a>. Said teams usually only adopted the managing practices of the method with less regard the technical practices. Robert C. Martin has an <a href="https://skillsmatter.com/skillscasts/8016-the-future-of-programming">interesting historical explenation</a> on why it is this way. And they fail because the one thing doesn't work without the other. Not for long at least.</p>
<p>What happens is that if you decide to just release more ofter and to be more flexible about the requirements and just to "go faster", it's crucial that your code base actually lets you do all of these things. For that it has to be <em>clean</em> enough to allow easy and frequent changed. If you don't refactor mercilessly and constantly, your code base will turn into a dump with time.</p>
<p>The growing dump doesn't hinder you much in the beginning and you actually start to become faster and reap the benefits of agile development, but after a while, the growing amount of ad-hoc solutions make it harder and harder to extend the system, implementing new functionality and changing existing ones takes longer and longer, and you slowly grind to a halt.</p>
<p>Keeping the code base clean requires skills and, maybe more importantly, discipline. This is why things like TDD and Pair Programming exist. It's much like keeping your kitchen sink clean while cooking. It's not as much fun as releasing features, but it's absolutely necessary. Otherwise you will create what Ward Cunningham called <a href="http://martinfowler.com/bliki/TechnicalDebt.html">Technical Debt</a>. And just like financial debt, it can be a useful tool, but if not taken care of, it can also make you bancrupt.</p>
<p>This is what I believe is happening in many democratic countries.</p>
<h2>Power and Knowledge</h2>
<p>What is democracy? It's "power of the people". That means that "the people" are (or should be) in charge of the government. All of them. And since that's not feasible (yet), all current implementations use a system of more or less directly appointed delegates. So the way I understand it is: The more directly "the people" can influence the law of a country, the more democratic is that country.</p>
<p>And of course what you really want is that whoever is in charge of your country should be able to make good decisions. How you define "good" is of course another question all together. In my opinion "long-term happiness" is still a much better metric than "money spent" but that's not what I want to talk about here.</p>
<p>What "being able to make good decisions" definitely means is being able to understand complex problems. Because most problems nowadays are quite complex. And the way to achieve that of course is through education. Jeffersons put this more eloquently than me:</p>
<blockquote>
<p>I know no safe depository of the ultimate powers of the society but the people themselves. And if we think them not enlightened enough to exercise their control with a wholesome discretion, the remedy is not to take it from them but to inform their discretion by education.</p>
</blockquote>
<h2>Educational Debt</h2>
<p>My theory is this: Ignoring the mandate for education but still demanding that the people are in charge is essentially the same as ignoring the need to keep your codebase clean but demand to spit out new features every two weeks.</p>
<p>What we have created is an Educational Debt. Too many people lack the essential skills to make or even recognise good decisions. As a consequence, they don't vote with an understanding of the complex problems that have to tackled. Instead they let themselves be guided by emotions, believes and partisan solidarity.</p>
<p>And I'm not talking about reading or maths skills here or a knowledge or historic events. The skills that a democratic citizen needs and that I haven't seen on any curriculum yet are</p>
<ul>
<li><strong>being compassionate</strong></li>
<li><strong>having a constructive discussion</strong></li>
<li><strong>exercising critical thinking</strong></li>
<li><strong>applying the scientific method</strong></li>
<li><strong>avoiding cognitive biases</strong></li>
</ul>
<p>Possible ways of teaching compassion include Virtual Reality, which literally lets you "walk in someone else's moccassins". Discussion, critical thinking and science is probably best tackled in schools although some paradigms will have to shift. Teachers need to stop that nonesense with a "single right answer", motivate student to challenge common believes and start realizing that <em>science</em> is really just <a href="https://www.youtube.com/watch?v=N9c7_8Gp7gI">"a negotiation between the best you can do right now and the stuff that is out there"</a>. For that it would probably be helpful to read and discuss actual studies and learn that discussions are not about being "right", but about collaborative discovery. To learn about cognitive biases I recommend to put <a href="https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow">Thinking Fast and Slow</a> on the reading list.</p>
<p>So instead of fighting the ignorants and their followers, let's put our energy towards creating a better education for the next generation but also for the current ones. Let's rethink if curricula with arbitrary standardized learning achievements are really the best way to motivate people. Let's reconsider if stuffing people into groups based on their birth year is the best environment for them to learn. And let's find out if we can create something better that static, linear media to express and explore their ideas in.</p>
<blockquote>
<p>It is not education, but education of a certain kind that will serve us. And the current model of western, urban-centered, school-based education, which is so often more focused on turning children into corporate units rather than curious snd open-minded adults, will only lead us further down the wrong path.
-- David W. Orr</p>
</blockquote>
<p>We need a new kind of education. And we need it soon.</p>More than Machines2016-12-15T00:00:00+01:002016-12-15T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2016-12-15:/more-than-machines.html<p>My opinion is probably more than a bit biased, but to me computers are incredible. Almost magical even. Like daemons from another sphere, all it takes is the right spell, and it will do your bidding (and like with these daemons, you have to be very careful which exact words …</p><p>My opinion is probably more than a bit biased, but to me computers are incredible. Almost magical even. Like daemons from another sphere, all it takes is the right spell, and it will do your bidding (and like with these daemons, you have to be very careful which exact words you use). My favourite quote on that topic comes from <a href="https://en.wikipedia.org/wiki/The_Mythical_Man-Month">The Mythical Man-Month</a>:</p>
<blockquote>
<p>The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. Few media of creation are so flexible, so easy to polish and rework [...] The magic of myth and legend has come true in our time. One types the correct incantation on a keyboard, and a display screen comes to life, showing things that never were nor could be.<br>
-- Fred Brooks</p>
</blockquote>
<p>Computers get this power through a property called <em><a href="https://en.wikipedia.org/wiki/Turing_completeness">Turing completeness</a></em>, named after the probably most influential computer scientist to have ever lived. In his 1936 <a href="https://www.cs.virginia.edu/~robins/Turing_Paper_1936.pdf">paper</a>, Turing proofed that you can construct a machine that can emulate any other conceivable machine. Or in less precise terms: a computer is not just a machine. It is <em>all</em> machines.</p>
<h2>Cutting the Wings</h2>
<p>So we have these incredibly flexible machines, that can become any other machine in the blink of an eye, and we use them to emulate <em>static</em> appliances with a fixed set of actions. And because we call them <em>apps</em> and <em>features</em> we don't realize just how much we are limiting ourselves with this paradigm.</p>
<p>This point deserves its own essay and luckily Paul Chiusano <a href="http://pchiusano.github.io/2013-05-22/future-of-software.html">already wrote it</a> in an excellent manner. So please head over and read his article, which not entirely coincidentally starts with the same Fred Brooks quote. It's a little on the wordy side but well worth the reading time. </p>
<p>I mean it. Please. Read it.</p>
<p>One could argue that a limited, static user interface is easier to use and therefore superior even if it cripples the user. But the original designers of graphical user interfaces did not think so. <a href="http://www.mprove.de/">Matthias Müller-Prove</a> gives a very conclusive overview of the history and development of the GUI, from <a href="http://www.mprove.de/diplom/text/3.1.2_sketchpad.html">Sketchpad</a> over the <a href="http://www.mprove.de/diplom/text/3.1.5_xeroxalto.html">Alto</a> to the <a href="http://www.mprove.de/diplom/text/3.1.9_macintosh.html">Macintosh</a>.</p>
<p>Sketchpad is seen as the first graphical user interface and had for its time futuristic feats such as direct manipulation, constraint-based layouting as well as a powerful template system which was an inspiration for Smalltalk, the object-oriented programming language and user interface of the Xerox Alto. There were also no applications visible on one of the first consumer-oriented computers, the Apple Lisa, which adopted the "real office" metaphor of the Xerox Star, which lets the user manipulates <em>documents</em> in a WYSIWYG way. Double-clicking on a document opened in, dragging it into the paper bin deleted it, and a new document was created by cloning a template.</p>
<p>It was only the hardware limitation of the Macintosh that forced the interface designers to divert from this more natural document metaphor and settle for the concept of applications. With this metaphor, you needed not simply an empty document to write something, but a <em>writer</em> application.</p>
<blockquote>
<p>Why don’t we have the compound document model in use today? Because the Macintosh was a 128-kilobyte machine with a single disk drive. A user couldn’t possibly have more than one tool in the computer at any time because there wasn’t room. Since only one tool could be used with a document, then the tool might as well handle the opening and closing of that document.<br>
-- Bruce Tognazzini argues in "Tog on Software Design"</p>
</blockquote>
<p>And when computing resources became more abundant, software designers were too busy copying and extending existing user interaction models, to reconsider the decision against a more natural, more powerful document-centric model, made because of the limitation of outdated hardware.</p>
<h2>Solving the Problems</h2>
<p>Today, personal computing is very far from what its inventors had envisioned. Instead of more or less generic objects that can easily be mixed and matched by the users to solve their problems, there is an "app" for every tiny itch. And instead of being able to adapt these solution to their own unique needs, users have to request and wait for new "features".</p>
<p>But not only does this scale terribly, it's also mathematically <em>impossible</em> to solve all the needs of every single user. If you manage to discover the actual needs of 80% of your total target group and then manage to build a solution that fits 80% of those needs, you are really good at your job. But you also only meet 64% of all requirements of all users. And that's for the optimistic case. More realistic numbers are probably 50% or 30%.</p>
<p>And things are getting rapidly worse as the Web and mobile platforms do their best to get rid of the last bastion of freedom and control - files. Venture-capital-driven companies with the-user-is-the-product business models are heavily incentivised to lock an always growing number of people into walled gardens and hinder information exchange with other systems as much as possible. The ensuing battle for users leads to almost every software product to become an inevitably bloated accumulation of ever more specialized features, diminishing the return on investment while mudding the user model with each new feature.</p>
<p>A prominent example of this trend is the seemingly ever increasing number of messaging services. While there was always a great number of such services, it used to be possible to use them all with a single client software. Services nowadays are closed-off silos entirely for business reasons, costing the autonomy and freedom of their users. Other symptoms are the <a href="http://observer.com/2015/10/why-evernote-is-struggling-and-how-technology-is-moving-in-a-new-direction/">failure of Evernote</a> and <a href="http://pchiusano.github.io/2016-10-13/view-inspired.html">bloating of Trello</a>.</p>
<h2>Returning the Power</h2>
<p>The only scalable solution is to give users the means to solve their own, unique problems. To <a href="http://www.nakedobjects.org/book/section1.html">"treat the user as a problem solver, not merely as a process follower"</a> as Richard Pawson puts it in his book on <em>Naked Objects</em>.</p>
<p>Instead of bloated silos, software should be a collection of coherent libraries that can be easily combined and modified. Business models could be based on use-based micro-payments which are paid by the end user, not by the direct service consumer. Users should be able to solve simple problems in a simple way by combining a couple of small concise libraries. In this regard, messaging and picture sharing are definitely simple problems.</p>
<p>Lucky for me, even such a world would not eradicate the need for professional software developers since complex problems will continue to require complex, custom-made solutions. But the proportion of time spent on essential tasks like understanding the problem, deducing a model and testing the solution would hopefully increase compared to time spent on insignificant implementation details. So the profession would be better described as <em>modeller</em> or <em>designer</em> than <em>coder</em>.</p>
<h2>Managing the Tasks</h2>
<p>I would like to use my fight against procrastination as an example. My whole life I was suffering from low self-discipline and often times found myself wasting days and weeks that I should have spent on important tasks. As a consequence, many opportunities were missed, many goals unreachable and my freelancing work always a little more stressful than necessary.</p>
<p>I've read every self-help book I could get my hands on and tried every productivity application I could find but could not benefit from any of them for more than a couple of weeks. Ultimately, my bad habits always caught up with me. I even started to come up with my own schemes to mitigate my low discipline. But nothing seemed to work.</p>
<p>It was only when I discovered Tim Urban's <a href="http://waitbutwhy.com/2013/10/why-procrastinators-procrastinate.html">thoughts on procrastination</a> that I started to form a useful model of my mental process and its weaknesses. And since I'm in the lucky position of knowing some of the spells to make the daemons in the magical machine do my bidding, I could express this model in software and test it on myself. It still took me three iterations but in the end I found a solution that has pretty much changed my life during the last couple of months.</p>
<p>Excited about my breakthrough, I was keen to share my approach with people I know are also struggling with self organisation, only to discover that my model couldn't help them since it doesn't fit their particular situations. It seems some personal problems can only be solved by the persons themselves. As software designers, our job should be to give them the power to do so, not to take it away.</p>Code and Bicycles2016-12-08T00:00:00+01:002016-12-08T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2016-12-08:/code-and-bicycles.html<p>One of the most inspiring texts that I've ever read is Bret Victor's <a href="http://worrydream.com/ClimateChange/">What can a technologist do about climate change</a>. Before reading it, I was always a bit ashamed of not working directly on this most urgent and extensive problem of humanity. Instead of working on alternative energy sources …</p><p>One of the most inspiring texts that I've ever read is Bret Victor's <a href="http://worrydream.com/ClimateChange/">What can a technologist do about climate change</a>. Before reading it, I was always a bit ashamed of not working directly on this most urgent and extensive problem of humanity. Instead of working on alternative energy sources, storage or distribution, I spent my days with comparatively small and trivial problems.</p>
<p>Victor's words motivated me to think about how I can use my knowledge, skills and passion to help mitigating the global climate change, even if somewhat indirectly. I determined that the field I'm most knowledgeable in is computing and software engineering, and to be most skillful in system analysis, software design and teaching. Most importantly, the thing I'm passionate about is probably reinventing wheels.</p>
<p>So earlier this year, I used a two-weeks stay in a Buddhist monastery to think hard about what it is that drives me and what I really want to do with my life. Specifically, I wanted to thoroughly analyse my motivation behind an idea that has been floating around my head for years. The idea is about reinventing the wheel big time with a <a href="http://blog.rtens.org/a-unified-computing-model.html">unified programming model</a>, but I haven't dared to take it seriously since having written my <a href="https://github.com/zells/thesis/blob/master/memoria/out/thesis.pdf">diploma thesis</a> about it.</p>
<p>The result of these two weeks is a <a href="https://github.com/zells/core/blob/master/manifesto.md">manifesto</a> and the conviction that my mission should be <strong>to augment the collective intelligence of humanity by increasing <em>Software Literacy</em></strong>.</p>
<h2>Learn to Code</h2>
<p>When I started looking for others who might share this mission, I found dozens of courses that all make a very similar promise: to teach you to <em>code</em> in a couple of weeks or months. Of many I've heard before but never really had a closer look. So I dug into a couple of them and was surprised to realize that something didn't feel right. There was something about their approach that irked me but I couldn't put my finger on it.</p>
<p>In a broad generalization, the usual process was that you choose a programming language and then do guided tasks of increasing difficulty that are automatically evaluated. The tasks were of the kind that a recruiter might use to asses an applicant's familiarity with a technology. Some courses also have an instant gratification system that rewards you with badges for completing tasks.</p>
<p>Having written <em>Software Literacy</em> on my banner I was frustrated that I couldn't completely get behind this <em>Learn to Code</em> movement and even more so that I couldn't put in words what bothered me about these courses. It just felt like they were focusing on the wrong thing.</p>
<h2>Learn to Bike</h2>
<p>And once again it was Alan Kay who <a href="https://youtu.be/N9c7_8Gp7gI?t=51">presented an excellent metaphor</a> for what I was feeling. But once again I did not understand his message right away and I didn't connect the dots until I replied to a <a href="https://news.ycombinator.com/item?id=13107281">comment on HackerNews</a> that was part of the feedback to above mentioned manifesto.</p>
<p>I never thought about how different the experience of learning how to ride a bicycle must be for children nowadays compared to how I learned it. Just suddenly these tiny balance bikes seemed to be everywhere and I remember being surprised by how young their riders sometimes were and how well they handled them. But I just though "neat" and failed to see the didactic implications of not using training wheels.</p>
<p>It seems to be a very intuitive and common approach when teaching something to children: Take the adult version of a thing, and change something so it's less likely to fail. The problem is that many times, this change destroys the <em>essence</em> of what you want to teach. On a bike with training wheels, it's impossible to learn the one skill you need for riding an actual bike: balancing.</p>
<p>I'm convinced that the opposite approach is way more effective and less frustrating. On balancing bikes, children learn the <em>essentials</em> - balancing, leaning into curves - first. It's still safe since their feet are always close to the ground. Once they've mastered these skills and feel confident, they get a bike with pedals. These add some new concepts and require some new skills but nothing too demanding. Pedals are <em>not</em> an essential part of bikes but solely increase its efficiency. The increase is that high that it inspired Steve Jobs to call computers <a href="http://www.bikeboom.info/efficiency/">"bicycle for our minds"</a>.</p>
<h2>Don't learn to code</h2>
<p>Code - textual formal instructions - is <strong>not</strong> essential to programming. Code plays the role of the pedals. It gives you a very efficient way of describing structure and behaviour and specific programming languages are suited differently well for formulating thoughts of a specific kind but all it does is to increase the programmer's efficiency.</p>
<p>And this is exactly what has been bothering me about these programming courses. They all start and focus on the code. On a specific language even sometimes. They construct a small, well defined universe with small exercises that keep the learner from failing. But it's the same mistake as putting training wheels on a bike. The learner never gets to actually feel the ground and while it might happen sporadically, this approach even impedes learning the <em>essential</em> skills of programming.</p>
<p>I have no definite list of what these essentials are. But my top candidates would be</p>
<ul>
<li>modelling</li>
<li>software design</li>
<li>debugging</li>
<li>understanding scales</li>
<li>managing complexity</li>
<li>dealing with uncertanty</li>
</ul>
<p>None of these require a student to write code and most of them not even to read it.</p>
<h2>Learn to Program</h2>
<p>So instead of teaching to <em>code</em>, I would love to see programming courses that teach to <em>program</em>. Preferably without touching code at all but still providing the student with tools to build running, living, buggy software. <a href="http://squeakland.org/">Etoys</a>, <a href="https://scratch.mit.edu/">Scratch</a> and even spreadsheets could be used for this purpose. These courses probably already exist and just spend less money on marketing.</p>
<p>A simple - albeit subjective - metric to know if a "balancing bike" approach to programming works is how the students <em>feel</em> when released into the "wild" and with how much confidence you can tell if they're ready. They should even have a good feeling for that themselves. It would probably be something like "this feels too slow", as children feel when they outgrow their balancing bikes.</p>
<p>If you only ever bike with training wheels, you are never really ready to take them off since you don't actually know how to bike. I remember my first time without them. It was a long-anticipated - but actually kinda arbitrarily chosen - moment. I felt ready and happy. My dad was pushing me to gain momentum and when he released me, it felt like flying for a moment. And then I landed face-first on the ground.</p>
<p>I imagine that students completing one of these courses feel the same way. You did all the exercises, collected all the badges, you feel ready and skilled. How frustrating must it feel to realize you really only know very little. I know that people learning TDD the "training wheels" way feel like this because I have taught them that way and saw their frustration when they couldn't apply their new skills to their real-world problems. An <a href="http://blog.testdouble.com/posts/2014-01-25-the-failures-of-intro-to-tdd.html">article on testdouble</a> (especially figure 1) describes this situation very nicely although I don't agree with their conclusion.</p>
<h2>Learn to Fly</h2>
<p>So whatever you're teaching, don't just put training wheels on your own tools but create new, simpler tools that concentrate on the essentials and let your students learn to fly by touching the ground every once in a while. And accept that they will have to fall a couple of times, so give them an environment where hitting the ground is not too painful.</p>
<p>And whatever you're learning, find out what exactly the masters of that skill spend most of their time with. This is probably something important. And with some luck, it's even something essential that lets you fly.</p>A Unified Computing Model2016-11-28T00:00:00+01:002016-11-28T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2016-11-28:/a-unified-computing-model.html<p>In 1963, while working at the Advanced Research Project Agency, J.C.R. Licklider wrote in <a href="http://worrydream.com/refs/Licklider-IntergalacticNetwork.pdf">his Memorandum</a> to the <em>Members and Affiliates of the Intergalatic Computer Network</em>:</p>
<blockquote>
<p>At this extreme, the problem is essentially the one discussed by science fiction writers: "how do you get communications started among totally …</p></blockquote><p>In 1963, while working at the Advanced Research Project Agency, J.C.R. Licklider wrote in <a href="http://worrydream.com/refs/Licklider-IntergalacticNetwork.pdf">his Memorandum</a> to the <em>Members and Affiliates of the Intergalatic Computer Network</em>:</p>
<blockquote>
<p>At this extreme, the problem is essentially the one discussed by science fiction writers: "how do you get communications started among totally uncorrelated "sapient" beings?"</p>
</blockquote>
<p>Alan Kay <a href="https://vimeo.com/22463791">referred to this</a> as the <em>communicating with aliens problem</em>. Licklider continues:</p>
<blockquote>
<p>But, I should not like to make an extreme assumption about the uncorrelatedness. (I am willing to make an extreme assumption about the sapience.)</p>
</blockquote>
<p>Licklider's "Intergalatic Computer Network" became the "ARPANET" which in turn became the "Internet", which quite well fulfills his vision of connecting every single person on the planet.</p>
<p>In the context of the Internet, the "aliens" are two independently developed computer programs and the problem is how to get them talking to each other. Since Licklider allows us to soften the <em>uncorrelatedness</em> requirement, we can assume that there exists a common language language that both services know how to speak, albeit it probably won't be the native language of either. What should this language look like?</p>
<h2>Current State</h2>
<p>One could argue that the "language of the Internet" is the Internet Protocol stack (TCP/IP), which allows one program on the internet to talk to any other program. But it only specifies <em>how</em> they can talk to each other, not <em>what</em> they can talk about or how to discover what the other one <em>means</em>.</p>
<p>It's analogous to the air, lungs and ears. Given enough those, I can certainly <em>speak</em> to any other human on the planet that is close by. And they can probably <em>hear</em> me, but that doesn't mean they <em>understand</em> me or that I can <em>talk</em> with them. This is the state that the IP stack leaves us with.</p>
<p>The most wide-spread <em>meaningful</em> language of the internet is the WorldWideWeb. It specifies how things can be addressed (with URIs/URLs) and how these things can present themselves (with HTML). It provides meaning by specifying <em>verbs</em> of what you can do with these resources (such as "post" and "get"). And most importantly it defines how communication is done (with HTTP).</p>
<p>The result is a <em>computing model</em> that turned out to be quite useful for accessing static documents but really not a good fit for doing anything more interesting. And over the last decades many million of man-hours have been poured into mitigating its design flaws.</p>
<p>I very much agree with Alan Kay's notion that "HTML has gone back to the dark ages and is one of the worst ideas since MS-DOS", as he said in <a href="https://youtu.be/oKg1hTOQXoY?t=1421">one of his most iconic talks in 1997</a>. I also remember him saying once that the web-browser "does too much and not enough". I think what he means is that there are way too many primitives in HTML which all have to be interpreted (doing too much) but it's not at all extensible (not enough). The second critique point also goes for HTTP which has a fixed number of <em>verbs</em> which just don't fit in many situations. But the worst design flaw is in HTTP, which assumes that all communication is initiated by the client and no state is preserved in the server.</p>
<p>How could this be done better?</p>
<h2>Proposal</h2>
<p>I propose to design a protocol based on a computing model that is an abstraction of all existing and conceivable models and is thus compatible with all and any of them. I would like to call this model <a href="https://github.com/zells/qi">Qi</a> which means "breath" and "air" but also "energy flow".</p>
<p>This model could be used as a meta-language to create a meaningful but extensible vocabulary. Two uncorrelated services could use this model to discover each others capabilities and use the vocabulary to transfer meaning. The model would also be used to safely transfer not only data between services but also dynamic behaviour (code of any kind, even binary programs) without the need to manually translate either.</p>
<p>I believe this model could play the role of a <a href="https://youtu.be/oKg1hTOQXoY?t=3085">"universal interface language"</a> and make communicating with aliens possible.</p>
<h2>Model</h2>
<p>[update: I simplified the model by extracting <em>composable</em>, <em>abstractable</em> and <em>distributed</em>. An up-to-date description of the model can be found <a href="https://github.com/zells/core/blob/master/model.md">here</a> ]</p>
<p>The model consists of <em>composable</em>, <em>dynamic</em>, <em>concurrent</em>, <em>abstractable</em> and <em>distributed</em> objects, called <em>cells</em>. The semantics of the model are defined by these properties.</p>
<h3>Composable</h3>
<p>A cell can contain any number of other cells as children. Each <em>child</em> has a name that is unique amongst its siblings. </p>
<div class="highlight"><pre><span></span>Child := <symbol>+
</pre></div>
<p>This forms a tree where each cell is a node and can therefore be addressed by a <em>path</em> containing the <em>names</em> of each child cell.</p>
<div class="highlight"><pre><span></span>Path := Name+
Name := Child
</pre></div>
<p>To move up in the tree, a path can also contain a reference to the <em>parent</em> of a cell as well as the <em>root</em> of the tree.</p>
<div class="highlight"><pre><span></span>Name := Child|<parent>|<root>
</pre></div>
<h4>Example</h4>
<p>Given the following tree structure</p>
<div class="highlight"><pre><span></span> °
/ \
A B
| |
C D
</pre></div>
<p>The canonical path of <code>D</code> is <code>°.B.D</code> where <code>°</code> denotes the root and <code>.</code> separates two names. A path from <code>C</code> to <code>D</code> would be <code>^.^.B.D</code> where <code>^</code> denotes the parent.</p>
<h3>Dynamic</h3>
<p>A cell may have dynamic behaviour in the form of a <em>reaction</em> which is executed every time the cell receives a <em>message</em>. The message is always a single cell, referenced by a path relative to the sender.</p>
<div class="highlight"><pre><span></span>Message := Path
</pre></div>
<p>A reaction can contain any kind of behaviour, including sending messages to other cells.</p>
<h4>Example</h4>
<p>Given the following cell structure.</p>
<div class="highlight"><pre><span></span> °
/ | \
A B C
</pre></div>
<p>If the reaction of <code>A</code> is to send <code>B</code> to <code>C</code> (written as <code><receiver> <message></code>),</p>
<div class="highlight"><pre><span></span>°.C °.B
</pre></div>
<p>then every time <code>A</code> receives any message, it will cause <code>°.B</code> to be sent to <code>°.C</code>.</p>
<h3>Concurrent</h3>
<p>All messages are received <em>concurrently</em> without any specific order. Furthermore, each message is sent by a <em>messenger</em> which will keep trying to deliver the message until it is received or the messenger decides it's not deliverable. This way, data flow can be synchronized without requiring a fixed order of execution. Therefore messages may be sent to cells before they exist.</p>
<h4>Example</h4>
<p>When calculating <code>2 * 3 + 4 * 5</code>, the summation has to wait for both factors to complete calculation. The following diagram illustrates the case where the calculation of <code>2*3</code> is delayed. </p>
<div class="highlight"><pre><span></span>a = 2*3 ##
b = 4*5 ##
c = a+b ~~~~~~~###
----------->t
</pre></div>
<p>The summation waits (denoted by <code>~</code>) until the calculation of both factors is completed.</p>
<h3>Abstractable</h3>
<p>Every cell has a <em>stem</em> cell from which it inherits its reaction and all children. Each inherited child and the reaction can be replaced by the <em>specialized</em> cell.</p>
<h4>Example</h4>
<p>Given a cell <code>A</code> with a child <code>C</code>. If a cell <code>B</code> has <code>A</code> as stem, it inherits <code>C</code> (denoted by lower-case <code>c</code>). </p>
<div class="highlight"><pre><span></span> A<--B
| ¦
C c
</pre></div>
<p>If a message is sent to <code>B.C</code>, the reaction of <code>A.C</code> is executed in the <em>context</em> of <code>B.C</code> which means all paths will be resolved relative to <code>B.C</code>. </p>
<p>If <code>A.C</code> has a child <code>D</code>, it is inherited as well.</p>
<div class="highlight"><pre><span></span> A<--B
| ¦
C c
| ¦
D d
</pre></div>
<h3>Distributed</h3>
<p>A cell can be distributed over multiple processes and machines. It is connected to a <em>peer</em> by sending it a <em>join</em> signal with information about how the peer can be reached. If a cell can't deliver a message, it will forward it to each of its peers in turn by sending them a <em>deliver</em> signal. If a peer can't deliver the message either, it responds with <em>failed</em>, otherwise with <em>received</em>. A peer is disconnected from a cell by sending a <em>leave</em> signal.</p>
<p>To be able to avoid endlessly forwarding messages in circular peer connections, a <em>deliver</em> signal contains a globally unique identifier. Messages are guaranteed to be delivered at most once, but there are no guarantees regarding the order of messages.</p>
<h4>Example</h4>
<p>Given a cell <code>A</code> in the process with the ID <code>111</code>.</p>
<div class="highlight"><pre><span></span> 111
+-----+
| |
| A |
| |
+-----+
</pre></div>
<p>If a new process (with the ID <code>222</code>) is created that contains also cell <code>A</code>, the signal <code>join A 222</code> is sent to process <code>111</code>. This adds a unidirectional connection from the cell in <code>111</code> to its peer int <code>222</code>.</p>
<div class="highlight"><pre><span></span> 111 222
+-----+ +-----+
| | | |
| A~~~~~~~~~>A |
| | | |
+-----+ +-----+
</pre></div>
<h2>Discussion</h2>
<p>The purpose of this document is to invite discussion by providing a precise but readable description of a proposed unified computing model. If you find possible design flaws or contradictions, or if you have any other feedback, e.g. regarding applicability or plausibility, please don't hesitate to <a href="http://rtens.org#contact">let me know</a>. You'll find a proof-of-concept implementation <a href="https://github.com/zells/qi">on github</a>.</p>Codemotion Milan 20162016-11-26T00:00:00+01:002016-11-26T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2016-11-26:/codemotion-milan-2016.html<p>My Codemotion spree of this year ended in the beautiful city of Milan. I was quite impressed by the sheer amount of talks and speaker and even more of their quality. Unfortunately I could only attend a few since I arrived during the first day and decided that my own …</p><p>My Codemotion spree of this year ended in the beautiful city of Milan. I was quite impressed by the sheer amount of talks and speaker and even more of their quality. Unfortunately I could only attend a few since I arrived during the first day and decided that my own talk could use one more practice round in the hotel speaking to myself in the mirror and since the trains were on strike that day, I decided to walk to the venue and have my my first gelato - which is compulsory in Italy even with 10° and rain.</p>
<p>When I finally arrived, I got distracted by a VR demonstration, which completely blew my mind and made me want to be in virtual reality all the time. <a href="https://en.wikipedia.org/wiki/Ready_Player_One">Ready Player One</a> came into my mind and I wondered how long knowledge workers will keep insisting on commuting to an office instead of just staying at home and meet in an virtual space. Guess the technology isn't quite there yet but the experience definitely got me thinking about how virtual worlds could be used as an interface to computers. Something along the lines of <a href="http://planetcroquet.squeak.org/">croquet</a> or <a href="http://www.opencobalt.net/">cobalt</a>.</p>
<p>Later that evening we taxied halfway across town for a very enjoyable dinner with the Codemotion team, speakers and sponsors. I loved the setting and the cocktail-party style with trays of finger-food making it's rounds through the crowd. The food was absolutely delicious, especially the tiny burgers. I'm very thankful to the organizers for that evening.</p>
<p>Next day was my moment of truth. I presented a brand new talk which was surprisingly preparation-intensive. Especially once I decided to make it completely live - meaning live coding and live slide-drawing. I was quite nervous because of the new format and new subject which might have been the reason why I ended up on a train in the wrong direction which led to me running from the train station to the auditorium to make it just in time.</p>
<p>The talk went surprisingly well, was great fun and successful in its objective to blow at least <a href="https://twitter.com/jesuswasrasta/status/802473304699310080">one mind</a>. Another outcome is that I'm currently planning to create a monthly Smalltalk meet-up in Berlin together with <a href="http://www.tddfellow.com/">Oleksii Fedorov</a>.</p>
<p>So thanks to Codemotion Milan for giving me the opportunity to talk about Smalltalk and try out a new presentation format. Won't definitely the last time I used it. </p>Wrong way driver2016-11-22T00:00:00+01:002016-11-22T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2016-11-22:/wrong-way-driver.html<p>Maybe I'm just a cynic and maybe this is just a rant but I think software development nowadays su... I'm highly discontent with the way software development is done. To be more specific, I've listed a bunch of incidental complications that make programming unnecessarily hard along with ideas how they …</p><p>Maybe I'm just a cynic and maybe this is just a rant but I think software development nowadays su... I'm highly discontent with the way software development is done. To be more specific, I've listed a bunch of incidental complications that make programming unnecessarily hard along with ideas how they could be avoided in the <a href="https://github.com/zells/core/blob/master/manifesto.md">zells manifesto</a>.</p>
<p>My theory is that programming is just way too complicated nowadays and what's worse is that it actually gets more complicated. But the need for people able to create, understand, modify and share software is ever increasing and will even more so in the future. So in recent years a number of (mostly online) courses for learning programming sprouted.</p>
<p>One of them if <a href="https://teamtreehouse.com/">treehouse</a> that I know only very little about but they seem to invest a lot in marketing. I suppose for that reason, youtube decided to recommend <a href="https://www.youtube.com/watch?v=i5qpS_D8Law">this video</a> to me. It shows Ryan Carson giving a big picture overview of the field of software development.</p>
<p>I'm not exactly sure what the video is trying to do. It certainly doesn't try very hard to make software development look easy. Since it's a marketing tool, it probably wants to make it look just complicated enough to convince you to book a course with them, but not too complicated to disillusion you.</p>
<p>I think a lot of people will agree with the contents of the video that this is <em>just the way it is</em> and they might even think that's a good thing. To me, the video shows almost every ten seconds something that is <strong>terribly wrong</strong> about the way things are.</p>
<p>It's things like </p>
<ul>
<li>having to chose a platform and device format up-front.</li>
<li>Being completely locked-in on iOS regarding hardware and software.</li>
<li>Depending of the approval of some company for what you are allowed to share with the world.</li>
<li>Having to deal with at least 5 technologies, including databases, when developing for the Web.</li>
<li>Putting code in static text files.</li>
<li>Creating designs with static images.</li>
<li>Developing in phases with one guy for each phase. </li>
<li>And of course having applications at all.</li>
</ul>
<p>Every single one of these points make me cringe.</p>
<p>A frightening thought for me is that there might be only a handful of people in the world that feel this way. So maybe in the end it'll turn out that I'm the wrong-way driver who thinks every body else is driving in the wrong direction.</p>
<p>But better ideas have been around since the 60s/70s. If you want to see a modern adoption of one of them, have a look at <a href="https://www.youtube.com/watch?v=QTJRwKOFddc">lively kernels</a>.</p>Codemotion Berlin 20162016-10-26T00:00:00+02:002016-10-26T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2016-10-26:/codemotion-berlin-2016.html<p>To get to this month's conference I didn't need plane nor train but could easily walk the couple of hundred meters to <a href="http://berlin2016.codemotionworld.com/">Codemotion</a> in the Kulturbrauerei. And not only that was new but also my talk on <em>Prototyping with Domain-Driven Design</em>. </p>
<p>You can find the <a href="/res/rapid_prototyping_with_ddd.pdf">slides here</a> and there is …</p><p>To get to this month's conference I didn't need plane nor train but could easily walk the couple of hundred meters to <a href="http://berlin2016.codemotionworld.com/">Codemotion</a> in the Kulturbrauerei. And not only that was new but also my talk on <em>Prototyping with Domain-Driven Design</em>. </p>
<p>You can find the <a href="/res/rapid_prototyping_with_ddd.pdf">slides here</a> and there is also a voice recording of the talk <a href="https://www.voicerepublic.com/talks/rapid-prototyping">here</a>.</p>
<p>The factory-atmosphere of the place was typically Berlin and the whole event was very well organized. Check out some awesome pictures <a href="https://www.flickr.com/photos/newthinking_de/sets/72157674861773860/with/30114374153/">here</a>. I'm already looking forward to <a href="http://milan2016.codemotionworld.com/">Milan</a> next month.</p>Codemotion Warsaw 20162016-09-17T00:00:00+02:002016-09-17T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2016-09-17:/codemotion-warsaw-2016.html<p>Last week I had the pleasure of presenting my talk on <a href="http://specificationbyexample.com">Specification by Example</a> (aka Behaviour-Driven Development) in an actual cinema at the <a href="http://warsaw2016.codemotionworld.com/">Codemotion</a> conference in Warsaw. <a href="/res/codemoton_roma_2014_Nikolas_Martens.pdf">You can find the slides here</a> from when I gave it <a href="http://blog.rtens.org/codemotion-2014-rome.html">in Rome two years ago</a>.</p>Why even casual programming is hard2016-06-10T00:00:00+02:002016-06-10T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2016-06-10:/why-even-casual-programming-is-hard.html<p>When I was searching yesterday for "what makes programming hard", none of the results really resonated with me. All pieces were about why it is hard to become a <em>professional</em> software developer. Most people seem to view programming as an all-in activity. Either you're in for the big win (a …</p><p>When I was searching yesterday for "what makes programming hard", none of the results really resonated with me. All pieces were about why it is hard to become a <em>professional</em> software developer. Most people seem to view programming as an all-in activity. Either you're in for the big win (a job), or you don't even start trying.</p>
<p>They talk about how problem analysis, modelling, software design, project management and so on make programming hard since they are all major challenges on their own. And for anybody who wants to become a professional developer, there are a multitude of resources and courses available. But what about the casual programmer? The every-day computer user who just has this small specific problem which could be easily solved by some machine magic? They have very limited options.</p>
<h2>Definitions</h2>
<p>When I say "programming", you probably think of nerdy people hacking on their keyboards, encoding instructions in some language like C, Java, PHP or Python. But the kind of programming I want to address is the <em>casual</em> programming. The cases where most people wouldn't even call it "programming". For example, if you create a <strong>spreadsheet</strong> that calculates your holiday expenses, you're programming. And even if you create <strong>slides</strong> of your holidays with penguins flying around on the click of a button, you're still programming.</p>
<blockquote>
<p>Programming is the activity of creating a <em>program</em>. A program is a set of instructions that, when interpreted, specifies how to <em>react</em> to <em>events</em>.</p>
</blockquote>
<p>This is my definition. It's probably not perfect, but let's work with it. The key terms here are <strong>event</strong>, <strong>react</strong> and <strong>instructions</strong>. In the case of slides, the event is <em>mouse clicked</em>, the reaction might be <em>text appears</em> and the instructions are created using a <em>specialized user interface</em>. In a spreadsheet, the event would be <em>this number changes</em> which causes <em>another number to change</em> as a reaction, following the instructions of <em>some formula</em>.</p>
<p>While I consider both of these to be "programming", other activities like <em>writing a Word document</em>, <em>making a video</em> and even <em>creating a web-site</em> don't fit the definition. Actually web-sites are edge cases because even without JavaScript, a hyper-link is the explicit instruction <em>browse to URL</em> to react to the event of <em>clicking on it</em>. That's not the slope I want to go down here though.</p>
<h2>Limitations</h2>
<p>More obvious examples of casual programming are macros in Word and Excel, beginner-friendly environments like <a href="https://scratch.mit.edu/">Scratch</a> and specialized tools like Excel, PowerPoint and Matlab. And while these are great tools for their use cases they are all limited in their capabilities - by design. I probably should not complain about the limitations of Excel since more than a few of my freelancing projects were basically replacing a spreadsheet with a web application.</p>
<p>And it always got me wondering: Why is it that somebody with a vast and precise domain knowledge, who can formulate complex dynamic model on a spreadsheet is incapable of creating even a simple web application? Of course there are many tools out there to create web-sites but they are usually even more limited than Excel. What is it about general purpose programming that makes it so much harder? And is that intrinsic complexity that can't be avoided? Or is it incidental and we just haven't tried hard enough to make it easier?</p>
<p>Every time I teach programming to children, friends or other developers, I get the feeling that there should be an easier way. That most complications are absolutely unnecessary. So I use special environments like <a href="https://scratch.mit.edu/">Scratch</a> and <a href="http://www.squeakland.org/">Etoys</a> to get the general ideas of across because they are wonderfully easiy to get started with. But even with Etoys, which is conceptually not limited in it's capabilities, I cannot create anything more complex than introductory examples myself. Pretty cool introductory examples with self-driving cars, but still somehow limited.</p>
<h2>Obstacles</h2>
<p>When I teach programming, I usually see my students struggle with the same obstacles. And I have the suspicion that they are the same fundamental reasons that make it annoying for experienced programmers. Every time I have to tell to myself "that's just the way it is" I wonder if that's really the case. And I wonder why the people in my search result don't see these as problems. Is it because they get so used to them that they accept them as unavoidable complications? The way most people learned to accept spam?</p>
<p>The following list is what I consider to be the fundamental reasons of why programming is hard to learn and unpleasant to practice.</p>
<h3>Set-up</h3>
<p>The first struggle appears even before you can start. Many programming languages are comically difficult to get started with. Maybe I'm asking for too much but spending half and hour to an hour for just setting-up the environment is often times frustrating, especially when time is limited. All language providers try to make this process as painless as possible but often they only achieve this for a single platform. </p>
<p>The by far easiest language to start with is JavaScript since everybody has a browser installed.</p>
<h3>Syntax</h3>
<p>So you finally have installed the programming environment of your choice and are ready to create your first program but you find something blocking your way: the syntax. So the very first thing is either to open the documentation or a tutorial. There is absolutely no way for anyone to guess how to do anything beyond basic arithmetic. Because it's just text, the language is not discoverable. This is a property it shares with the command line interface. Before you get anything done, you need to memorize obscure combinations of characters. In other words: In order to command the demon, you need to learn the spells. And the demon is very unforgiving towards even the tiniest mistake.</p>
<p>The best way is to avoid syntax all together with tile-based programming environments like <a href="https://scratch.mit.edu/">Scratch</a> and <a href="http://www.squeakland.org/">Etoys</a>.</p>
<h3>Interactivity</h3>
<p>Since the days of punch cards, the feedback cycles of programming have increased immensely. What used to be several hours of waiting for the operators to feed your cards has become milliseconds after pressing a button. But still most languages don't let you interact directly with its elements. Debuggers try to bridge this gap but don't seem to be part of the standard tool set of most languages. It's almost impossible to find an introduction or tutorial that discusses how and when to use it. And even if your language comes with a good debugger, it usually only lets you inspect, but not change what you see.</p>
<p>The only language that I know of which allows true interactivity is Smalltalk and it's derivatives like <a href="http://squeak.org/">Squeak</a> and <a href="http://pharo.org/">Pharo</a>.</p>
<h3>Sharing</h3>
<p>Because of all these obstacles it'll probably take a while before you create your first program that you're actually proud of. But the day will come on which you want to show your creation to your mother. But how? Now you regret having saved on the set-up costs by choosing a interpreted language. And even if you can compile it to something she can run with a double-click, if she only has a phone, you're out of luck - unless that's what you were going for from the start. But even then she might have the wrong type of phone. And what if you change something and want her to get the new version?</p>
<p>This is where web applications really shine since all you need to send is a URL but they force your user to be on-line and you to learn not one but three to five languages.</p>
<h3>Dependencies</h3>
<p>One reason why it's hard to share your program is because it will probably be using some other programs, so-called libraries. These dependencies need either to be bundled up with your program or your mother needs to download them before she can run it. And your dependencies probably have dependencies as well which might depend on the same programs as others but in different versions. And that's where it really gets complicated.</p>
<p>Here web applications have it easier as well but even those need to be installed somewhere. The only way that I know of to avoid the dependency struggle is to use web-services instead of downloading.</p>
<h3>Security</h3>
<p>Now that you use web services for everything, you realize that all of them require you to authenticate, to proof that you are you. So you still end up with dependencies on libraries that handle the authentication. But even if you get the services to trust your program, to convince the user to trust it is a whole different ball game. Having chosen to create a web application now bites you in the back because there is no way you can access the user's file system or talk to any program running on his computer. But at least you can ask for permission to access the camera and location. If you get your user to download and run your program locally, then you basically get to do everything you want on their machine. Copy personal information, delete their holiday pictures. You name it.</p>
<p>Web application still have probably the best permission system since they don't require any up-front permission but still can access some things. Many platforms are adapting a more fine-grained permission system but they still have a long way to go.</p>
<h3>Serialization</h3>
<p>Another problem with using web services is that now you are using a library which does not live in the same space as your application. Every piece of information you exchange with it needs to go through a thin wire. That not only slows everything down, it also means to have to squeeze your data really thin before you send it and inflate the strings you receive. This is called serialization and it's a major pain. You also need to do it if you want to keep any information after your program was shut down because the hard drive is really just a very long but equally thin wire.</p>
<p><a href="http://squeak.org/">Smalltalk</a> is once again the only environment that I know of which uses an <em>image</em> that just keeps everything that happens around. You still need to serialize data before sending it to anything outside the image though.</p>
<h3>Society</h3>
<p>There also seems to be the conviction amongst programmers that programming needs to be hard and if it's not hard then "it's not real programming". I'm not sure if that's some sort of elitism or if they just want everybody to suffer as much as they did. So there is a huge technological but also social gap between people creating software and people consuming software. And unwillingly or not, the programmer community does its best to keep it that way. Neither do they provide the tools to make it easy for everyone to create programs, nor a particularly open attitude. Instead they create walled gardens, golden cages and cryptic jargon.</p>
<p>Many developer communities try hard to be as inclusive to new-comers as possible but there is still a lot of segregation between technologies (because other languages are always worse than mine).</p>
<h3>Practices</h3>
<p>Lastly, programming is hard because a lot of times it deals with complex problems that are simply complex. And it's just too easy to get it wrong or to make a mess. Since programming is a very creative activity, there is no simple process you can follow to get it right. So even if all the above obstacles were eliminated. If you can easily and securely create and use programs but most of them are broken or too messy to work with, it's all in vain.</p>
<p>There are many practices like <em>open source</em>, <em>shared ownership</em> and <em>automated testing</em> that help to implement a good solution correctly in a clean and sustainable way. But this might actually be an inherent complexity that you can't easy get rid of.</p>
<h2>Solutions</h2>
<p>So it seems that the way to avoid most of the described struggles would be to create web applications with Smalltalk (nd having arrived at that conclusion, that's definitely something I will try soon). But it always struck me as weird that although I'm convinced of Smalltalks advantages and have been for a while, I have yet to use it for something more than basic exploration.</p>
<p>My dream solution would be a mix between <a href="http://pharo.org/">Pharo</a>, <a href="http://www.squeakland.org/">Etoys</a> and the WorldWideWeb. The result would be an interactive programming environment where all objects are persistent and can be accessed from any device, secured by asymmetric encryptions. Building such a system, that removes all incidental complexity and enables every computer user easily and securely create and share dynamic models is what I'm planning to do with <a href="http://zells.org">zells</a>.</p>Bhutan Part Three2016-05-24T00:00:00+02:002016-05-24T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2016-05-24:/bhutan-part-three.html<p>Only little more than a month to go. Time for an update. I'll try to make this one quick.</p>
<p>This article is part of a series. Check out the <a href="http://blog.rtens.org/tag/bhutan.html">other ones</a> if you haven't yet.</p>
<h2>Thimphu</h2>
<p>So what's been going on in the big small city? Well for once there …</p><p>Only little more than a month to go. Time for an update. I'll try to make this one quick.</p>
<p>This article is part of a series. Check out the <a href="http://blog.rtens.org/tag/bhutan.html">other ones</a> if you haven't yet.</p>
<h2>Thimphu</h2>
<p>So what's been going on in the big small city? Well for once there have been a couple of more forest fires. One was so bad that I couldn't bike home that evening because the smog was to thick.</p>
<p><img alt="Smog of nearby forest fire" src="/static/img/bhutan/20160317_145705.jpg"></p>
<p>And the three of us (that's my sister, my brother in-law and me) actually started Dzongkha lessons. That's the official language of Bhutan, besides English. That's definitely the most exotic language I'll ever learn with around 400k users. That if you don't count Latin which of course has close to zero users.</p>
<p>Languages in Bhutan is a little messy since it's a small country so most people I know speak four languages or more. The school system is in English since most text books and curricula and some teachers are important from India. That means every Bhutanese who went to a school has some pretty robust English skills. Dzongkha is usually taught in school as a separate subject and sometimes history is taught in Dzongkha. Besides that it's mostly used for official communication. Then everybody with access to a TV probably knows Hindi since there are only two Bhutanese channels and many many many Indian. Then most people speak their local language which can be very local or one of the other two big ones. Many people speak also Nepali and one or two local Indian languages.</p>
<p>This creates a pretty mixed-up day-to-day communication. If two Bhutanese talk to each other you can probably grasp the topic since about 20% of their words will be english.</p>
<p>So twice a week the three of us sit in this very nice looking classroom in the Dzongkha Learning Center and listen to our <em>lopen</em>. There are no books on grammar and no consistent spelling of words, at least with the Latin alphabet. So it's a little bit tricky but none the less big fun since the classes consist mostly of our quite old and very experienced teacher telling us about his life and how life in Bhutan is in general. SO it's as much a social class as it is a language class since protocol plays an important role here.</p>
<p><img alt="Our classroom" src="/static/img/bhutan/20160311_090254.jpg"></p>
<h2>Paro Tshetchu</h2>
<p>End of march was one of the largest festivals of the year in Paro. Allegedly it's also the <em>posh one</em> where everybody dresses up the best they can and it's all about see and be seen. So of course we all dressed up including my little niece and I bought a Gho (the traditional garmet) for the occasion.</p>
<p>I went with a friend and stayed at his girlfriend's parents' house which was quite the experience it itself but the festival was really something. But let pictures speak.</p>
<p><img alt="Paro tsechu" src="/static/img/bhutan/20160320_130533.jpg"></p>
<p><img alt="My own Gho" src="/static/img/bhutan/20160320_165544.jpg"></p>
<h2>Farming Potatoes</h2>
<p>A couple of days later I was on my way to Paro again. This time with a sleeping bag in my luggage. My destination was the new Happy Chips potato-farm-to-be a little north of Paro, just underneath the ruins of the Drukgyal Dzong. </p>
<p>For three days I helped Farmer Sangay and the rest of the Happy Chips gang to prepare the fields for plantation. First order of business: build picks. The rest of the days was spent clearing the fields from rocks and weed and digging a pool to wash the potatoes in. On the last evening we soaked in a hot stone bath which took four hours to get hot enough because none of us had a really good idea of how to heat stones.</p>
<p><img alt="Our self-made picks" src="/static/img/bhutan/20160325_152633.jpg"></p>
<p><img alt="Digging the pool" src="/static/img/bhutan/20160324_122219.jpg"></p>
<p><img alt="Clearing the irigation channel to fill the pool" src="/static/img/bhutan/20160324_161355.jpg"></p>
<p><img alt="Morning view" src="/static/img/bhutan/20160326_072237.jpg"></p>Bhutan Part Two2016-03-05T00:00:00+01:002016-03-05T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2016-03-05:/bhutan-part-two.html<p>Somehow I thought that time would slow down a bit if I move to such a different place. But it didn't. Not a bit. A third of my time in Bhutan is already over - 121 days to go, 61 down.</p>
<p>So I guess it's about time that I update this …</p><p>Somehow I thought that time would slow down a bit if I move to such a different place. But it didn't. Not a bit. A third of my time in Bhutan is already over - 121 days to go, 61 down.</p>
<p>So I guess it's about time that I update this little travel log with what I've been doing the last days. One thing is clear: I enjoyed every single one of it.</p>
<p>This article is part of a series. Check out the <a href="http://blog.rtens.org/tag/bhutan.html">other ones</a> if you haven't yet.</p>
<p><img alt="20160120_151606.jpg" src="static/img/bhutan/20160120_151606.jpg"></p>
<h2>Some Hikes</h2>
<p>Especially the warm and sunny winter days, which are perfect for hiking up to the prayer flags to catch a wonderful view of my new home, Thimphu. Taking a short cut back through the woods turned out to be not such a great idea though since most trees and bushes here have thorns.</p>
<p><img alt="20160123_122216.jpg" src="static/img/bhutan/20160123_122216.jpg"></p>
<p>But that little excursion gave me appetite for a longer hike so on the next day we went up to the nearby monastery, Phojeding. After three hours marching uphill we reached a building complex that houses over 60 monks during the summer time, but only 7 monks stayed for the winter. By those were received with cookies and Ngaja aka Milktea - black tea with milk and plenty of sugar. A very young monk was eager to use the opportunity to practice his English and translated our conversation with one of the elders. On the way down I discovered that Bhutanese snowmen seem to have long pointy noses.</p>
<p><img alt="20160123_124221.jpg" src="static/img/bhutan/20160123_124221.jpg"></p>
<p><img alt="20160124_121741.jpg" src="static/img/bhutan/20160124_121741.jpg"></p>
<p>This hike also led to my first contribution to <a href="https://www.openstreetmap.org">OpenStreetMap</a> which I always use for hiking since in Germany the quality of the maps is incredible and I haven't found a single trail that was not also marked in them. Naturally, the amount of information for Bhutan is a lot less but still considerable at least concerning streets. I was positively surprised how easy it was to add <a href="https://www.openstreetmap.org/#map=15/27.4856/89.6022&layers=C">our path</a>.</p>
<p><img alt="20160306_113427.jpg" src="static/img/bhutan/20160306_113427.jpg"></p>
<p>Unfortunately I haven't been to the mountains much since, partly because of weather, partly because a series of forest fires motivated us to stay away from the trees. During about three weeks, there were almost constantly something burning and the helicopter (the only one in the country) could be heard every other day. One day, the valley was filled with thick smoke caused by a major fire some ten kilometres away.</p>
<p><img alt="20160212_134814.jpg" src="static/img/bhutan/20160212_134814.jpg"></p>
<p><img alt="20160215_164953.jpg" src="static/img/bhutan/20160215_164953.jpg"></p>
<h2>Some Dance</h2>
<p>A very rare treat for me was the opportunity to attend a <em>Puja</em> in the home village in Punakha of a good friend of my sister's. Pujas are religious ceremonies that almost every family does once per year and for special occasions like the birth of a child or a successful harvest. During two or three days, monks stay at the house, chanting and making music which sounds like something <a href="https://youtu.be/9p0G7ulk5y8?t=253">this</a>. I heard that sound almost every day when walking through Thimphu since Pujas are usually held during the two month winter vacation.</p>
<p><img alt="20160129_185709.jpg" src="static/img/bhutan/20160129_185709.jpg"></p>
<p><img alt="20160129_235707.jpg" src="static/img/bhutan/20160129_235707.jpg"></p>
<p>All 25 households of the village were invited, there was a lot of food and since I didn't want to be the only one using a spoons, I learned to eat rice and chilli with my hand which was harder than I thought.The trick is to squeeze the rice into a ball and then dip that into the chilli sauce. This also seems to be the reason why rice is always served and kept on a separate plate. I especially enjoyed the <em>Ara</em>, a rice wine which is a little sweeter than Sake and traditionally served hot mixed with fried egg.</p>
<p><img alt="20160130_151316.jpg" src="static/img/bhutan/20160130_151316.jpg"></p>
<p>Until late at night the villagers and monks danced and sang together. I didn't record it myself but <a href="https://www.youtube.com/watch?v=lvaVQe30Ay4">this video</a> comes pretty close to what it sounded and looked like. While I was trying to learn the moves, one of the group from Thimphu that I was with informed me that we have been challenged to a rap battle by the youngsters. Unbelieving I came outside were a group of eight to fourteen year old were assembled and a little boy was indeed already rapping in Hindi while another was beatboxing. Luckily I still knew a couple of Blumentopf pieces by heart.</p>
<p><img alt="20160130_074328.jpg" src="static/img/bhutan/20160130_074328.jpg"></p>
<p><img alt="20160131_101421.jpg" src="static/img/bhutan/20160131_101421.jpg"></p>
<p><img alt="20160131_100441.jpg" src="static/img/bhutan/20160131_100441.jpg"></p>
<h2>Some Work</h2>
<p>Back in Thimphu I started a new project at <a href="http://drukhost.com">drukhost</a>, a local software development company. To kick-off the project, we did the probably first <a href="http://ziobrando.blogspot.com/2013/11/introducing-event-storming.html">event storming</a> workshop in Bhutan. The idea is to create a platform for Bhutanese movies about which you can currently only get very sparse information on facebook.</p>
<p>Another project I got quite excited about is to create tools for running complementary currencies. I wrote about this in my <a href="http://blog.rtens.org/the-problem-with-money.html">previous article</a> and also created a <a href="http://groupcash.org">project homepage</a>. I want to find a group to start a community currency in Thimphu but so far I have little more than an idea and am not sure if the remaining four months are enough time.</p>
<p>So I'm going almost every day to the office now where I keep warm with plenty of tea and work with two other guys on a website for Bhutanese movies. Going by bike is a lot of fun in the morning but the climbing the 300 metres elevation back up is quite an evening work-out.</p>
<h2>Some Travel</h2>
<p>Driving here requires some serious getting used to. Traffic rules are pretty much non existing, cars tend to suddenly stop in the middle of road without warning and signalling before making a turn is widely considered unnecessary. The fact that most of the streets have no markings and are not lit at night helps as little as random cows and horses standing around. And while bike helmets are mandatory, seat belts are not and absolutely nobody puts them on.</p>
<p>But at least in the city most streets are paved. Windiness plus potholes reduce the cruising speed on country roads to an average of about 40 km/h, turning even small distances into a day trip. It's funny how the perspective changes though. While going five hours from Berlin to Munich seems like a major trip back home, spending eight hours on a bumpy road seems like a minor thing here like when we went to Gelephu last month.</p>
<p>So I wasn't too opposed of taking the car to the far east to visit Mountain Hazelnuts although it's about 16 hours to Bumthang and then another 6 to the headquarters in Lingmethang. But I also didn't mind to exchange that 16 hours on a bumpy road for 35 minutes in the air. Although it felt a little bit like cheating. But the view from the plane was incredible.</p>
<p><img alt="20160207_113313.jpg" src="static/img/bhutan/20160207_113313.jpg"></p>
<p>And I got plenty of road adventure. From Bumthang you we had to cross a 4000m high pass. Including snowy roads, steep cliffs and no railings. And at almost the very top, the driver suddenly stops and steps outside. Curiously I follow him and find him look at a flat tire. That wouldn't have been a problem hadn't the spare wheel been flat as well. So we had no other option than to walk to the next village and wait almost 3 hours for another car to pick us up. But the Ngaja was good.</p>
<p><img alt="20160202_125933.jpg" src="static/img/bhutan/20160202_125933.jpg"></p>
<p><img alt="20160206_143313.jpg" src="static/img/bhutan/20160206_143313.jpg"></p>
<p><img alt="20160206_160356.jpg" src="static/img/bhutan/20160206_160356.jpg"></p>
<p><img alt="20160206_164623.jpg" src="static/img/bhutan/20160206_164623.jpg"></p>
<p>During the next three days I got to know a lot about hazelnuts, shared my knowledge about software development, tried Bhutanese whisky, enjoyed the subtropical climate and most of all an evening of hot-stone baths next to a beautiful river. All in all a very nice getaway.</p>
<p><img alt="20160205_135343.jpg" src="static/img/bhutan/20160205_135343.jpg"></p>
<h2>Some Culture</h2>
<p>Almost half the days of February were holidays, including two days for the Bhutanese new year, three for the king's birthday and even two more for the birth of the crown prince.</p>
<p>This gave me the perfect chance to witness the Punakha Tchechu, a traditional Bhutanese festival. Since my sister got pretty sick two days before, she stayed in Thimphu with her husband and I went together with two German friends who were visiting at that time. Taking a Taxi for a two-and-a-half hour ride felt unusual to us but it turned out to be common practice for the locals. So we dressed up in Gho and Kira, drove to a beautifully located resort and went to bed early to not miss the presentation of the secret scroll at six in the morning on the next day. Getting there that early required waiting on the pitch black dirt road for a taxi for over half an hour but we made it in time - just to be turned away at the gates. Turns out foreigners can only see the scroll with special permission. Bummer.</p>
<p><img alt="20160219_135104.jpg" src="static/img/bhutan/20160219_135104.jpg"></p>
<p>The general admission would only be three hours later. Enough time enjoy the view on the Punakha Zong from the river and get some breakfast. And although I won't even try to put the <a href="https://www.youtube.com/watch?v=3TuRtrOAWPY">colours, the masses of people, the dancing and the music</a> into words, let me just say that it was completely worth the wait.</p>
<p><img alt="20160219_100937.jpg" src="static/img/bhutan/20160219_100937.jpg"></p>
<p><img alt="20160219_131607.jpg" src="static/img/bhutan/20160219_131607.jpg"></p>
<p>A little less crowded was the second cultural highlight. During an unconventional world tour, Joss Stone gave a concert in Thimphu. I didn't expect it to be a huge event but I was still surprised when we entered something that was little more than a school gym. When Joss entered the stage there were maybe 300 people there so during her second song she jumped down from the stage and animated almost everybody individually to come closer and dance with her. A very unique experience.</p>
<p><img alt="20160223_174219.jpg" src="static/img/bhutan/20160223_174219.jpg"></p>
<p><img alt="20160223_201025.jpg" src="static/img/bhutan/20160223_201025.jpg"></p>
<h2>Some Spring</h2>
<p>Meanwhile the seasons have started turning, the trees have started blooming and today was the first day that really felt like spring. I still can't believe it's already March.</p>
<p><img alt="20160312_124959.jpg" src="static/img/bhutan/20160312_124959.jpg"></p>
<p>I sincerely hope that I start writing more frequently than once per month but knowing myself I wouldn't bet on it.</p>The Problem with Money2016-02-10T00:00:00+01:002016-02-10T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2016-02-10:/the-problem-with-money.html<p>For a long time I've been having the faint feeling, that something is fundamentally wrong with money. With the way it's created, the way it's used, the way it drives our actions. I could never quite put my finger on it but the feeling was always there when I thought …</p><p>For a long time I've been having the faint feeling, that something is fundamentally wrong with money. With the way it's created, the way it's used, the way it drives our actions. I could never quite put my finger on it but the feeling was always there when I thought about economy, capitalism and welfare. Only recently I could put the puzzle together and found a way to fix money.</p>
<p>When I learned about <a href="https://en.wikipedia.org/wiki/Social_entrepreneurship">social entrepreneurship</a>, I immediately felt that it might be a solution for many problems caused by capitalism and although I'm convinced that it will replace conventional businesses in the long run, it doesn't go deep enough. Then along came <a href="https://bitcoin.org/">Bitcoin</a> just as the global economy was collapsing. And while using cryptography and the <a href="https://en.wikipedia.org/wiki/Block_chain_(database)">block chain</a> to free trading from bank-controlled money is ingenious, it still didn't feel right to me and I only recently discovered why. The last piece of the puzzle was my <a href="http://blog.rtens.org/category/bhutan.html">move to Bhutan</a> in the beginning of the year. Learning about some of the problems of the local monetary system got me thinking and talking again about money. And when a friend told me about <a href="https://en.wikipedia.org/wiki/Complementary_currency">complementary currencies</a>, it finally clicked.</p>
<h2>Bank Money</h2>
<p>In his book <a href="http://www.feasta.org/documents/moneyecology/contents.htm">"The Ecology of Money"</a>, Richard Douthwaite defines three types of money: Bank money, government money and people money. It surprised me to find out that most of the money we use is <em>bank money</em>, created by private banks when giving loans for profit. There are several problems with this kind of money, nicely described in the <a href="http://www.openmoney.org/top/omanifesto.html">open money manifesto</a>. All these problems are design flaws that can be avoided by improving the design of a currency.</p>
<p>One fact that most people accept as a law of nature is that acquiring money always costs in the form of <strong>interest</strong>. Interest benefits the rich and impairs the poor. Not a surprised in a system designed by the rich. Compound interests make it easy to get money if you have money and hard (if not impossible) if you don't. It also puts a <strong>profit-pressure</strong> on the every business that ever took a loan. This condemns the economy to eternally grow just to make even, if necessary on the expense of the community and environment. The result is an economy centred around profit-maximization instead of sustainability.</p>
<p>A phenomenon that makes interest seem unavoidable is <strong>inflation</strong>. Since money becomes worth less every day, you <em>have</em> to earn interest just not to loose wealth. But inflation is a side-effect of how a currency is created and managed. A better design could incorporate the incentives that inflation provides without its disadvantages.</p>
<p>Another key problem is the <strong>scarcity</strong> of money. It's kept scarce artificially by a <strong>bank monopoly</strong> to control it's value. This is necessary since the value of bank money is completely artificial. It's only worth something because it's hard to get and everybody seems to want it. But again, it's only hard to get for those who don't have much. And most times there is not enough when it's needed the most. When building schools or community centres for example. Because money always chases the highest return-on-investment, it tends to concentrate in a few profit centres. Therefore many regions experience a <strong>capital drainage</strong> - most of the available money is spent outside the community and never returns - increasing it's scarcity in these regions.</p>
<p>And because it is controlled by private banks, money is actually <strong>hard to move</strong>, thus inhibiting trade. Transferring it to someone requires either to hand over physical tokens or relying on a third party such as banks and credit institutes. Either way implies a transaction cost which limits the size of feasible transactions, apart from the fact that most people are not even able to open an account with any bank or credit institute.</p>
<h2>Cryptography</h2>
<p>This becomes visible in a country like Bhutan where there are no credit cards and online-banking is in its infancy. While attending the <a href="http://www.up.co/communities/bhutan/thimphu-bhutan/startup-weekend/7382">start-up weekend in Thimphu</a>, I noticed that payment was a big challenge for many business ideas since the only way to pay for a service is by sending cash, sending a cheque or going to the bank to make a transference in person. At the workshop I also met a entrepreneur who told me he once tried to set-up a payment service but was not granted the required licence by the central bank.</p>
<p>I started thinking if a cryptographic currency like <a href="https://bitcoin.org/">Bitcoin</a> could be used to solve the payment problem. But that would require a Bitcoin-Ngultrum exchange service which would probably need a banking licence as well. And although I'm a big fan of the block chain, Bitcoin shares a design flaw with conventional currency: the artificial value through scarcity.</p>
<p>Apart from that, Bitcoin also seems to be facing technical and governance problems. Mike Hearn even goes as far as to claim that <a href="https://medium.com/@octskyward/the-resolution-of-the-bitcoin-experiment-dabb30201f7">Bitcoin has failed</a>. I believe a reason might be that purely monetary incentives are just not enough to keep a community viable. In such a system, the concentration of wealth and formation of monopolies is motivated which is harming the community. The result is that the vast majority of <a href="https://bitcoin.org/en/vocabulary#hash-rate">hashing power</a> now lies in the hand of a few people.</p>
<p>Another core assumption of Bitcoin that I disagree with concerns trust. A declared feature of Bitcoin is that users can transfer the ownership of a coin without having to trust each other or any third party. The only thing they have to trust is the block chain which is controlled by whoever has the most computing power in the world. But what is trade without trust?</p>
<h2>Community</h2>
<p>So instead of using a currency that denies trust, let's use one that fosters it. Instead of basing the value on artificial scarcity, let's design a currency that is abundant and based on real value. And instead of accepting the yoke of perpetual growth, let's create a interest-free monetary system that is under the control of the community that uses it.</p>
<p>As I said this to my brother in-law, he responded "This sounds like what the Chiemgauer is doing." which is how I learned about <a href="https://en.wikipedia.org/wiki/Complementary_currency">complementary currencies</a>. The <a href="http://www.chiemgauer.info/">Chiemgauer</a> is a local currency used in the region around Chiemsee, created in 2003 as a school project. It implements an idea by Silvio Gesell of <em>money that rusts</em>. Gesell argued that money, like natural products should slowly lose its value over time and thus create a spending incentive. <em>Chiemgauer</em> is the proof that this idea actually works with a turnover of over 7 million units in 2014.</p>
<p>I discovered that there are <a href="https://en.wikipedia.org/wiki/Local_currency#List_of_local_currencies">hundreds of complementary currencies</a>, some fairly large like the <a href="http://www.wir.ch">WIR Bank</a> in Switzerland but most are small by design to support a local community. A very comprehensive description of many currencies along with good arguments supporting them can be found in <a href="http://www.lietaer.com/writings/books/people-money/">People Money</a>. But they all have in common that they require a central accounting system or a central issuer of physical tokens.</p>
<h2>Groupcash</h2>
<p>Since I still wanted to solve the online-payment problem, physical cash was not an option and setting up a central bank for community money would require a licence which was apparently hard to get. What I needed was a system that combines the de-centralized features of a cryptographic currency with the community-building properties of a local currency. In such a system, transactions could be done directly without relying on a third party by trusting eachother, every user would be in control of its own account, and could even print its own cash if needed.</p>
<p>So I started to design a system with these properties which I named <a href="http://groupcash.org">groupcash</a>. The result is a software system based on digital signatures. Money is created by value-creating companies issuing delivery promises. The promises are signed by a regulatory entity that guarantees the compatibility and plausibility of these promises. Each promise is worth one unit which can be transferred by signing it over to a new owner. To avoid double-spending, transferences can be validated by the company backing the promise, but this does not have to be done immediately - depending on how much the giver is trusted.</p>
<p>So although there is a single entity regulating the issuing, it cannot issue units on its own and has no role in the trading. And although validation is done by the backing companies, the owner of a promise can independently prove their rightful entitlement to the delivery of the promise.</p>
<p>A more detailed description of the system including algorithms to issue, transfer and validate units can be found <a href="https://github.com/groupcash/core/">here</a>. I also implemented these algorithms in a <a href="https://github.com/groupcash/php/">PHP library</a> and intend to create a web application that can be used to easily set-up a local currency community. Peer-to-peer and mobile applications will follow once the system is proven to be useful.</p>
<h2>Resources</h2>
<p>More information and resources on complementary currencies can be found here</p>
<ul>
<li><a href="http://groupcash.org">Groupcash Project Page</a></li>
<li><a href="http://complementarycurrency.org">Complementary Currency Resource Center</a></li>
<li><a href="http://cc-literature.de">Complementary Currency Literature</a></li>
<li><a href="http://CommunityForge.net/en">CommunityForge</a> - Open-source tools</li>
<li><a href="http://openmoney.org">Open Money Project</a></li>
<li><a href="http://regiogeld.de">RegioGeld e.V.</a></li>
<li><a href="http://irta.com">IRTA</a> - International Reciprocal Trade Association</li>
<li><a href="http://socialtrade.org">STRO</a> - Social Trade Organization</li>
<li><a href="http://qoin.org">QOIN</a> - Consultancy and Tools</li>
</ul>Bhutan Part One2016-01-17T00:00:00+01:002016-01-17T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2016-01-17:/bhutan-part-one.html<p>Two weeks ago, I packed my bags, got on a plane and flew to the small kingdom Bhutan in south-east Asia, where I'm gonna stay for the next six months. So mostly for keeping track of my time here myself, I want to <a href="http://blog.rtens.org/tag/bhutan.html">write about it</a> every once in a …</p><p>Two weeks ago, I packed my bags, got on a plane and flew to the small kingdom Bhutan in south-east Asia, where I'm gonna stay for the next six months. So mostly for keeping track of my time here myself, I want to <a href="http://blog.rtens.org/tag/bhutan.html">write about it</a> every once in a while. Hope you enjoy.</p>
<h2>24 Hours</h2>
<p>My journey started on a Sunday morning at 34m above see level and -11°C and ended roughly 24 hours later on a Monday afternoon, 2300m higher, 27°C warmer and one swiss pocket knife poorer - because being able to bring it to Dheli by plane doesn't mean I can get it out of Dheli by plane.</p>
<p><img alt="20160104_134835.jpg" src="static/img/bhutan/20160104_134835.jpg"></p>
<p>And it was only when I saw the Himalaya mountains, including Mount Everest, through the window of a mostly empty DrukAir A320, that I started to believe that I was actually moving to this unique far-away country.</p>
<p>How did this happen?</p>
<p>I remembered skyping with my sister and her husband one day - both of them have been living in Bhutan for the last three years - when my sister suddenly informed me, that they have found a way to get me a working visa for half a year and that they have basically already decided that I must take advantage of that.</p>
<p>Turned out they were very right about that and a couple of months later me and my brother in-law Adrian would board a train that would bring us to Frankfurt, from where we would fly to Dheli and a couple of hours later continue to Bhutan.</p>
<p><em>"Ladies and gentlemen, we're appraoching Paro. Please fasten your seatbelts and make sure your seat backs and tray tables are in their full upright position."</em></p>
<p><img alt="20160104_141358.jpg" src="static/img/bhutan/20160104_141358.jpg"></p>
<p>The descent to Paro is really something to remember. During the final ten minutes or so, the machine makes a series of sharp turns through narrow valleys, just a couple of hundred meters above ground. Seems like a good reason why only a handful of specially trained pilots are landing here.</p>
<h2>Setting up Camp</h2>
<p>The first couple of days I spent setting-up my working environment. A new country was a good enough reason for me to play around with some Linux distros. Since internet flatrates are not a thing in Bhutan and 4GB cost 6€, I stuck to the smaller ones but in the end stayed with Ubuntu.</p>
<p><img alt="20160111_151327.jpg" src="static/img/bhutan/20160111_151327.jpg"></p>
<p>My sister and her husband rent the top floor of a cute little house up in the hills above the 100 thousand people strong capital <em>Thimphu</em>. The spare room on the left of the entrance is where I'm staying. Since street names - if existing - don't matter and there are no house numbers, my new address is "Yellow house, Upper Motithang, above the traffic circle, near Peaceful Resort, Thimphu, Bhutan".</p>
<p>What I unterestimated is how could ten degrees can be if you only have mobile radiators and almost no insulation. And it took a couple of cold nights until I realized that it takes a sleeping bag plus four blankets to keep me warm and asleep.</p>
<h2>All Action, no Talk</h2>
<p>My first weekend coincided with the first <a href="http://www.molhr.gov.bt/molhr/?p=2981">Start-Up Weekend in Bhutan</a>. The goal of this format is to develop an idea into a viable product in just two days.</p>
<p><img alt="20160110_150041.jpg" src="static/img/bhutan/20160110_150041.jpg"></p>
<p>This was very fortunate for me since it gave me the perfect opportunity to get to know the entrpreneur community of Bhutan. And I was deeply impressed by the sharp minds, the drive and dedication of everyone I talked to.</p>
<p>Out of the more or less 30 people that were attending, 14 pitched an idea - ranging from putting haircutters next to schools, over custom cardboard box manufacturing, grocery delivery service, appartment market place, until kira & gho* design app.</p>
<p>*) "Kira" (a long skirt) and "Gho" (kinda like a bathrope) are the names of the traditionals costumes which are still worn by the majority of the people.</p>
<p><img alt="20160109_180114.jpg" src="static/img/bhutan/20160109_180114.jpg"></p>
<p>After the one-minutes pitches, the participants voted for the three ideas they would like to work on, and then form teams for the five ideas with the most votes. I joined the team of Rinzin who wanted to help people with the yearly renewal of their vehicle fitness certificates. Apparently these are not only very costly when not done in time but also time consuming. His solution was to provide a reminder-service and I new that I could probably develop something simple that fits the bill over the weekend.</p>
<p><img alt="20160110_215950.JPG" src="static/img/bhutan/20160110_215950.JPG"></p>
<p><img alt="20160109_120106.jpg" src="static/img/bhutan/20160109_120106.jpg"></p>
<p>Staying true to the motto "all action, no talk", one of the first things we did was to go out on the street and talk to potential customers - aka car owners - to find out if there is even a need for such a service. This way we found out that what these people really want is to somehow make the whole procedure less painful and faster. Especially the paying which has to be done personally and sometimes requires up to 4 hours standing in line.</p>
<p><img alt="20160110_220241.JPG" src="static/img/bhutan/20160110_220241.JPG"></p>
<p>So in the end our proposal was "Deputy" - a service to help people with their car licencing, or even any bureaucratic nuisance. And it got us second place.</p>
<h2>Going South</h2>
<p>The following week we made a trip to the very south of the country. The 220km on windy, only partly tarred roads took us over 8 hours. But the views made it worth while.</p>
<p><img alt="20160112_113922.jpg" src="static/img/bhutan/20160112_113922.jpg"></p>
<p><img alt="20160112_123511.jpg" src="static/img/bhutan/20160112_123511.jpg"></p>
<p><img alt="20160112_164009.jpg" src="static/img/bhutan/20160112_164009.jpg"></p>
<p>We crossed the 4000m high Dachula pass with a beatiful view on the snow-topped Himalaya at about noon and from then on there was only one direction which was <em>down</em>. Our destination was a small community near <em>Gelephu</em>. At 300m above seelvel we found a rather sub-tropical climate with tons of palm and banana trees.</p>
<p>The reason for our trip was for Adrian and a partner of his to have a look at the potatoe farm where the raw material for Adrian's <a href="http://happy.bt/chips">potatoe chip factory</a> was growing. Having little to no experience with agriculture, this was a very interesting experience for me. I wouldn't call myself an expert in potatoe farming now, but I definitely learned a lot.</p>
<p><img alt="20160113_113344.jpg" src="static/img/bhutan/20160113_113344.jpg"></p>
<p><img alt="20160113_154833.jpg" src="static/img/bhutan/20160113_154833.jpg"></p>
<p><img alt="20160114_094119.jpg" src="static/img/bhutan/20160114_094119.jpg"></p>
<p>We were accomodated in a small rural house that was implementing the <em>wet bathroom concept</em> - as it is common in most parts of Bhutan. That means a bucket instead of a shower and a hole in the floor instead of a toilet. Something to get used to.</p>
<p>Thanks to the fresh supply of vegetables and a skilled cook, the food was extraordinarily good. Like pretty much every meal I had since I arrived, it was mostly rice and cooked vegetables. And chili. Bhutanese dishes all contain at least some chili. Luckily my high Sriracha consumption has prepared me for this.</p>
<p>Next to the house was a decent sized football field and I learned two things this afternoon. First, these kids know how to play. Second, sprinting a hundred meters is not something I can do anymore just like that.</p>
<p><img alt="20160114_141008.jpg" src="static/img/bhutan/20160114_141008.jpg"></p>
<p>On our way back we stopped to pick up some cookies. These are small disks made from compressed saw dust and can be used to fuel micro-gasifiers - small ovens that burn not only the wood but also the smoke, allowing smoke-less cooking. I've never heard of this technology before and was immediately fascinated by it. The <a href="http://dazin.org">project <em>Dazin</em></a> has the goal of providing these stoves and the cookies to the rural households in Bhutan using a innovative distribution scheme. I you don't know what I'm talking about, you should <a href="http://dazin.org">give it a read</a>.</p>
<h2>Snow!</h2>
<p>Now I'm back in Thimphu, enjoying the food and good talks with friendly people. Today it snowed! And since it was the first time this year, it was promptly declared a region-wide holiday by the government - as it's custom.</p>
<p><img alt="20160120_084612.jpg" src="static/img/bhutan/20160120_084612.jpg"></p>
<p>In the meantime I created a small CMS for the website of the <a href="http://happy.bt/">Happy Green Cooperative</a> using my <a href="https://github.com/rtens/domin">user interface generator</a> and also wrote a small script to monitor the remaining volume of our internet connection and send emails if it gets too low. So you could say I'm having a really good time here.</p>
<p>That's it for now from my side. More will follow.</p>Science-Driven Development2015-12-14T00:00:00+01:002015-12-14T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2015-12-14:/science-driven-development.html<p>Ever once in a while everything seems to fall into place and suddenly the connection between previously unconnected dots becomes obvious. During the last couple of days, I've had such a moment. In this article I describe the reasoning behind my conclusion that <a href="http://theleanstartup.com">The Lean Start-Up</a>, <a href="http://agilemanifesto.com">Agile Development</a>, <a href="http://specificationbyexample.com">Specification by …</a></p><p>Ever once in a while everything seems to fall into place and suddenly the connection between previously unconnected dots becomes obvious. During the last couple of days, I've had such a moment. In this article I describe the reasoning behind my conclusion that <a href="http://theleanstartup.com">The Lean Start-Up</a>, <a href="http://agilemanifesto.com">Agile Development</a>, <a href="http://specificationbyexample.com">Specification by Example</a>, <a href="http://en.wikipedia.org/wiki/Test-driven_development">Test-Driven Development</a> and <a href="http://waitbutwhy.com/2015/11/the-cook-and-the-chef-musks-secret-sauce.html">Elon Musk's Secret Sauce</a> are all based on the same underlying principle: the scientific method.</p>
<h2>Models</h2>
<blockquote>
<p>The scientific method is the process by which scientists [...] construct an accurate [...] representation of the world <a href="http://teacher.nsrl.rochester.edu/phy_labs/appendixe/appendixe.html">wolfs</a></p>
</blockquote>
<p>The <em>representation of the world</em> is also known as <em>model</em> or <em>theory</em>, depending on its level of acceptance and applicability. A model may describe a phenomenon accurately only within certain limitations. We use many different models in our everyday lives in order to predict the outcome of our actions and we start forming then as early as when we learn that crying will yield food and attention. When it comes to achieving your goals, the known accuracy of your model is crucial.</p>
<p>For example, in order to save Lois Lane, Superman can pick between at least two models</p>
<div class="highlight"><pre><span></span><span class="err">A) Catching something saves it from harm.</span>
<span class="err">B) Force equals mass times acceleration.</span>
</pre></div>
<p>Using the first model, he will catch her while flying horizontally and rip her apart. If he uses the second model, he will realise that since he cannot changes Lois' mass, he has to also fly downwards and minimize her de-acceleration.</p>
<p>Both models are "correct" - meaning they hold under certain circumstances - as dropping an egg from the kitchen counter can easily demonstrate. Proving model A wrong is a little harder and might include dropping eggs from tall buildings. Falsifying model B is even harder and would probably require accelerating an egg to a larger fraction of the speed of light. A key principle of scientific models is that you can only show where it is incorrect, never that it's correct. There is no Truth, just , less wrong".</p>
<p>Improving the accuracy of our models might be the most important thing in our lives. And the only way to do so is by letting them collide with reality and discard the assumptions that didn't survive the collision. With each iteration you'll have a slightly less-wrong model. This is called the scientific method.</p>
<p><img alt="Scientific Method" src="static/img/scientific_method.png"></p>
<h2>Loops</h2>
<p>The <a href="http://waitbutwhy.com/2015/11/the-cook-and-the-chef-musks-secret-sauce.html">"Secret Sauce"</a> of Elon Musk an other highly successful people is that they're really good at going through these assumption/validation loops. And the common principle of the before mentioned software development practices is that all of them optimize going through loops on different scales.</p>
<p>I identified three loops, whereas the outer precedes the inner.</p>
<p><img alt="Software Development Loops" src="static/img/development_loops.png"></p>
<h3><span style="color:red">Value</span></h3>
<p><strong>Assumption</strong> What we're building is valuable to somebody.</p>
<p><strong>Scale</strong> Weeks to months</p>
<p><strong>Validator</strong> Market</p>
<p><strong>Optimization</strong> Deliver working software continuously (agile) and collect real data from users and quickly as possible (lean)</p>
<h3><span style="color:green">Behvaiour</span></h3>
<p><strong>Assumption</strong> This is how the system is supposed to behave.</p>
<p><strong>Scale</strong> Hours to days</p>
<p><strong>Validator</strong> Customer</p>
<p><strong>Optimization</strong> Have costumer close-by (agile) and specify system in common language (BDD, Specification by Example)</p>
<h3><span style="color:blue">Code</span></h3>
<p><strong>Assumption</strong> The behaviour is implemented correctly.</p>
<p><strong>Scale</strong> Seconds to minutes</p>
<p><strong>Validator</strong> Tests</p>
<p><strong>Optimization</strong> Automate tests and keep them fast (TDD)</p>
<h2>Experiment is Supreme</h2>
<p>Using the scientific method to solve engineering problems has the pleasant side-effect that it replaces inefficient discussions consisting mostly of guessing with the design and execution of experiments. Instead of guessing if your product actually solves a problem, build a simple prototype and find out. Instead of guessing the missing specification, turn around and ask the customer. Instead of discussing which software design works better, re-factor and run the tests.</p>
<p>Endless discussions can be an indicator that an assumption is based on a "magical" theory which cannot be tested and require faith to be accepted. Such a theory does not qualify as a scientific theory and should not be used in a decision-making process.</p>
<p>What I've experienced as a main hurdle when applying these methods is to avoid the error of mistaking an hypothesis for the explanation of a phenomenon, without performing experimental tests. Sometimes "common sense" and "logic" tempt us into believing that no test is needed. <a href="http://teacher.nsrl.rochester.edu/phy_labs/appendixe/appendixe.html">wolfs</a> These believes can go very deep and questioning them might feel like an attack on our core values.</p>
<p>But being able to apply the scientific method openly and rationally to your projects and your life will greatly enhance your chances of success.</p>FrOSCon 20152015-08-25T00:00:00+02:002015-08-25T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2015-08-25:/froscon-2015.html<p>Last weekend, it was the 10 years anniversary of <a href="https://www.froscon.de">FrOSCon</a> and I got the chance to present "The pyramid is a lie" - a talk about multi-level testing inspired by <a href="https://twitter.com/everzet">Konstantin Kudryashov</a>'s talk <a href="https://skillsmatter.com/skillscasts/5899-modelling-by-example">Modelling by Example</a>. <a href="/res/the_pyramid_is_a_lie_slides.pdf">You can find the slides here</a> and you can <a href="https://joind.in/talk/view/15041">rate the talk here</a>.</p>
<p>As …</p><p>Last weekend, it was the 10 years anniversary of <a href="https://www.froscon.de">FrOSCon</a> and I got the chance to present "The pyramid is a lie" - a talk about multi-level testing inspired by <a href="https://twitter.com/everzet">Konstantin Kudryashov</a>'s talk <a href="https://skillsmatter.com/skillscasts/5899-modelling-by-example">Modelling by Example</a>. <a href="/res/the_pyramid_is_a_lie_slides.pdf">You can find the slides here</a> and you can <a href="https://joind.in/talk/view/15041">rate the talk here</a>.</p>
<p>As last year, the conference was a blast and very well organized. I'm especially happy that <a href="https://twitter.com/ElectricMaxxx">Maximilian Berghoff</a> took the opportunity to treat the subject in <a href="https://blog.mayflower.de/5309-Testen-an-der-Domain.html">his blog</a>. And thanks for your <a href="https://twitter.com/ElectricMaxxx/status/635079976753209344">feedback</a>. Can't wait for next year.</p>DPC 20152015-07-01T00:00:00+02:002015-07-01T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2015-07-01:/dpc-2015.html<p>Last weekend I had the extraordinary pleasure of presenting my talk on <a href="http://github.com/watoki/tempan">Template Animation</a> at the <a href="http://www.phpconference.nl/">Dutch PHP Conference</a>. If you happened to attend: thanks for showing up although it was the first slot after the social event =) and also: I'd appreciate your <a href="http://joind.in/talk/view/14237">feedback</a>.</p>
<p>The conference was extremely well organized …</p><p>Last weekend I had the extraordinary pleasure of presenting my talk on <a href="http://github.com/watoki/tempan">Template Animation</a> at the <a href="http://www.phpconference.nl/">Dutch PHP Conference</a>. If you happened to attend: thanks for showing up although it was the first slot after the social event =) and also: I'd appreciate your <a href="http://joind.in/talk/view/14237">feedback</a>.</p>
<p>The conference was extremely well organized, and I especially enjoyed the presentation by Ross Tuck on how <a href="http://joind.in/talk/view/14219">Awesome Command Busses</a>. Also, having two extra days for exploring Amsterdam turned out to be the best idea I had all year. Hope to be there again next year.</p>Computer Revolution2015-03-06T00:00:00+01:002015-03-06T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2015-03-06:/computer-revolution.html<p>I just came across <a href="http://twitter.com/ibdknox">Chris Granger</a>'s essay <a href="http://www.chris-granger.com/2015/01/26/coding-is-not-the-new-literacy/">"Coding is not the new literacy"</a> and although I strongly agree with his overall notion, I disagree with his premise "Being literate isn't simply a matter of being able to put words on the page, it's solidifying our thoughts such that they …</p><p>I just came across <a href="http://twitter.com/ibdknox">Chris Granger</a>'s essay <a href="http://www.chris-granger.com/2015/01/26/coding-is-not-the-new-literacy/">"Coding is not the new literacy"</a> and although I strongly agree with his overall notion, I disagree with his premise "Being literate isn't simply a matter of being able to put words on the page, it's solidifying our thoughts such that they can be written." and since this is an important topic for me I didn't want to restrict my thoughts to 140 characters.</p>
<h2>Coding <em>is</em> Literacy</h2>
<p>As far I understood it, Chris' main point is that "Coding is not the fundamental skill", <em>modelling</em> is. He compares coding to writing by stating that "Being literate isn't simply a matter of being able to put words on the page". And that's where I disagree. Being <em>literate</em> means exactly that: "being able to put words [from your head] on the page". It also means doing the reverse and the meaning has somewhat expanded during the last century but it also means exactly that.</p>
<p>In fact I would like to use the <a href="http://en.wikipedia.org/wiki/Literacy">expanded definition</a> of literacy:</p>
<blockquote>
<p>The ability to [...] understand and use the dominant symbol systems of a culture.</p>
</blockquote>
<p>So it's really all about decoding (understanding) and encoding (using) thoughts with symbols. Hence coding <em>is</em> a form of literacy. It's just not well suited for most kinds of thoughts and I think that's where Chris' pain is coming from. But maybe I'm projecting since this is also my pain. But more on that later. </p>
<h2>Literacy and Thinking</h2>
<p>The second part of his premise is that "Being literate [means] solidifying our thoughts such that they can be written." But writing is not necessary here since everything that can be written, can be spoken. The thought itself doesn't gain anything from being <em>written</em> down. It's the putting it in words (written or spoken) that makes a difference.</p>
<p>Writing down my thoughts is a strategy I use myself quite often to clarify them. This is actually a main reasons why I'm writing this article. But I could also just tell them to my <a href="http://en.wikipedia.org/wiki/Rubber_duck_debugging">rubber duck</a> instead. I just feel slightly less ridiculous writing them.</p>
<p>I don't think, writing makes me better at thinking though. Having to put my thought in words probably does. But not much. If there is one thing that really challenges and improves my thinking skills it's good discussions with people I respect. There is no immediate need for literacy to do that though. Two comfortable chairs in a quite room is more than enough.</p>
<p>But still I'm not having this particular discussion over a cup of green tea in my favourite coffee house - although I would love to. Because I am literate and fortunate enough to own a computer with internet access, I was able to <em>read</em> Chris' essay and respond to it by <em>writing</em> this here. This is the value of literacy. Being able to have discussions without the limits of time and space. This way I can acquire the thoughts of Chris just as I can acquire the thoughts of Aristotiles. And while it's highly improbable that I ever share a tea with the former, it's impossible with the latter. But despite the millennia in between, the old Greeks still influences the way we think about the world today. Because we an still read their thoughts.</p>
<p>And it's reading new ideas that challenges own ideas and make me think about them and ultimately write them down. So it's the dispute, not the writing that (hopefully) improves my thinking skills. If I had to choose between being able to read or write, I'd choose reading without hesitating. </p>
<h2>Modelling is Key</h2>
<p>Where I completely and utterly agree with Chris (and it turns out, my good friend and colleague <a href="https://twitter.com/rjenke/status/573794551888015360">Robert Jenke</a> as well) is that <strong>modelling is the fundamental skill</strong>. To build a model is necessary in order to put it in software. Just like formalising a thought is necessary before you can write it down. But I have to disagree with "Modelling is the new literacy". It's not. Being able to externalizing your mental models using software, that's literacy.</p>
<p>It's not an coincidence that Chris mentions Alan Kay, the guy who got me excited about modelling in the first place. (At this point I would like to urge every programmer and teacher to absorb as much of Alan's thoughts as possible.) Like him and Chris, I strongly believe that being able to play around (aka experiment) with models is probably the best way of discovering and learning complex ideas and this is exactly what Alan and others tried to do with computers in the 70s and 80s.</p>
<p>That was decades ago. But still, <a href="https://www.youtube.com/watch?v=oKg1hTOQXoY">"the computer revolution hasn't happened yet."</a> Why? Because we are still using computers only as a replacement for existing technologies. Better paper and pen. A lot more powerful and interconnected paper and pen that has changed the way we access and distribute information but not what <em>kind</em> of information. The single most distinguishing thing that computers can do that paper can't is to execute dynamic models of our thoughts. But yet only a tiny part of humanity use the capabilities or even know how to use them.</p>
<p>I really want to make this clear: being able to write down the way you think as dynamic, living software is fundamentally different and exponentially more powerful than writing down your thoughts with static words. It's not only recording thoughts, but <em>thinking</em> itself. Or in Chris' words:</p>
<blockquote>
<p>To put it simply, the next great advance in human ability comes from being able to externalize the mental models we spend our entire lives creating.</p>
</blockquote>
<p>The analogy between coding and writing is quite compelling. Just like writing down thoughts forces you to put them into words and thus clarify them, encoding a dynamic model forces you to think about it on a whole different level. A big part of my job as a software engineer is picking the brains of so-called <em>domain experts</em>. People who usually know very well how something works, but most times this knowledge is implicit. My job is then to make it explicit enough to be able to encode it in the programming language of my choice.</p>
<p>This means my ultimate goal is to put a part of the mind of this person into a machine. If done well, the machine can then do the thinking for the person. Only a <em>lot</em> faster. This might sound scary to some but it's what software engineers have been doing ever since the first machine instruction was executed.</p>
<h2>The Problem with Programming Languages</h2>
<p>Chris seems to ignore that humanity is already "able to externalize the mental models" - through coding. There are hundreds and thousands of programming languages out there. They are just not very approachable, or easy to learn. It's like if the only "language" we would have to write down our thoughts was mathematical notation. It's a great notation for a whole category of thoughts but it's just a little too complex to be adopted by the majority of people. Sure you can describe a circle as <code>(x-a)² + (y-b)² = r²</code> but usually it's a lot easier to write "circle" or even draw a circle. It might not be an <em>exact</em> circle, but usually that's not a problem.</p>
<p>And most programming languages is to dynamic models what mathematical notation is to thoughts. They are powerful tools but just way too complex for everyday stuff. I regularly attend the local <a href="https://coderdojo.com/">CoderDojo</a> meet-up where me and other "mentors" are trying to teach young people aged 5-15 how to program. Now it's really when you're sitting down with a ten year old that you realize how incredibly complex these languages really are. And the sad thing is that this complexity is incidental. It's a side product. It's not necessary. But it keeps us from learning and using them.</p>
<p>The answer to "How do I make a rectangle with text in it and when you click on it, it becomes red?" should not be "This bunch of HTML + CSS + JS". Just like you should not need to know about Pythagoras' theorem to be able to draw a circle. All you should need is a pen and a surface and your personal <em>idea</em> of a circle. We are still using languages that make it easy for the computer, instead we need to focus on making it easy for the human.</p>
<p>Of course a lot of people are doing exactly that. Trying to make programming easier for humans. That's why Excel is so widely used to build simple models. Because it's (relatively) easy and you can "touch" it and play around with it. And it's what Chris Granger and his associates are working on as well with <a href="http://lighttable.com/">Light Table</a> and the recently announced <em>eve</em> project which sounds like Excel on steroids. But I'm afraid that like Excel, it will be somewhat limited and only work well for a certain class of models. Although I'm looking forward to be proven wrong.</p>
<h2>So what Now?</h2>
<p>It's always easier to criticise existing solutions than to come up with a better one. So I take my hat in front of everybody who is trying and doing something about it. I hope that some day I will join that group as well. Until then let me describe what my ideal programming environment would look like.</p>
<p>There is actually one piece of software that comes remarkably close: <a href="http://www.squeakland.org/">Etoys</a>. And again it's no coincidence that it's designed for children and by Alan Kay. In Etoys, you can create objects by drawing them and you can give them behaviour by using tile-based programming. So it's almost trivial to "remote" control a virtual car or make the same car follow a track automatically. But you can also do complex things like the Etoys environment itself since the underlying platform, Smalltalk, can be reached from anywhere.</p>
<p>So my ideal programming environment would use a user interface similar to Etoys (maybe without tile-based programming or at least not the default option) but completely based on distributed, concurrent, composable and abstractable entities. I call them <em>zells</em> and wrote about them in my <a href="https://www.researchgate.net/publication/50841568_Design_and_implementation_of_a_distributed_software_platform_based_on_asynchronous_messages">Diploma Thesis</a>. The whole system would consist of nothing but these <em>zells</em> in a single, global address space (for easy sharing and publishing) and the only instruction would be "send <em>zell</em> to <em>zell</em> as message".</p>
<p>Re-usage is an important principle in software engineering but I agree with Chris that "the idea that we can reuse components without having to change them [...] has caused us more harm than good." Components need to be malleable so we can use them as a starting point but adjust them to our specific needs. We can not expect the creator of a software to account for all possible usages of his product. So if a peace of software is not exactly doing what you want it to do, you should be able to change it. But that requires literacy. We need to be able to read and write software.</p>
<p>It almost stroke me as odd that when it comes to text, there has always been a lot more reading than writing. But in the software world it seems to be the opposite. True literacy means that we can exchange dynamic models of our thinking with software the way we exchange our thoughts with text now. My ideal programming environment would allow us to have discussions using these models. Somebody could implement a model of how he thinks a part of the society works and I could change his model to incorporate my own view of the world or argue against it with a completely different model. The difference is that we wouldn't have to explain our thoughts to each other and hope that the other one understands our mental model and builds a similar one in his brain. Instead we could send each other our mental models directly and experiment with the thinking of other people. We could make predictions and verify the correctness of the models. Build upon them and improve them. We could do real science and thus step by step understand the world a bit better. We could record and make our thinking available without the limit of space and time.</p>
<p><em>This</em> would be a computer revolution.</p>Building web applications with watoki2015-03-05T00:00:00+01:002015-03-05T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2015-03-05:/building-web-applications-with-watoki.html<p>I've been working for about a year now on a project named <a href="http://github.com/watoki"><strong>w</strong>eb <strong>a</strong>pplication <strong>to</strong>ol <strong>ki</strong>t</a> (short <em>watoki</em>) and thought if I ever want anybody besides me to use it, I better write about how.</p>
<p><em>watoki</em> a collection of libraries that provide infrastructure commonly needed by …</p><p>I've been working for about a year now on a project named <a href="http://github.com/watoki"><strong>w</strong>eb <strong>a</strong>pplication <strong>to</strong>ol <strong>ki</strong>t</a> (short <em>watoki</em>) and thought if I ever want anybody besides me to use it, I better write about how.</p>
<p><em>watoki</em> a collection of libraries that provide infrastructure commonly needed by web applications - think loosely couple web framework. The goal of each library is to be as lightweight as possible and to make it easy for the client code to stay independent of the infrastructure. You can find an overview of all the libraries <a href="http://github.com/watoki">here</a>.</p>
<p>So in this article I would like to give you a step-by-step guide of how I would a simple web application with this tool kit. So here we go. Let's build a ... (drum roll) ... <em>blog</em> application (because nobody has ever done that). We're gonna take a very light-weight approach and then reduce maintenance cost by using a rendering and web delivery library. So in the end only two libraries are presented here but it should be enough to get you started.</p>
<p>You find the complete code of this application on <a href="https://github.com/rtens/demo-blog">github</a>. The section titles link to the commit that contains the code changes of the sections so you can browse the entire code at that state and play around with it.</p>
<h2><a href="https://github.com/rtens/demo-blog/tree/01761ba184a3922e647d804fe5c878198bafcb01">Starting Small</a></h2>
<p>Since we are all hip and lean and agile, let's build an MVP version (Minimal Viable Product, <em>not</em> Most Valuable Player) of our blog consisting of an overview and a single article. Here is the entire directory structure:</p>
<div class="highlight"><pre><span></span><span class="err">demo-blog</span>
<span class="err">|- index.html</span>
<span class="err">'- articles</span>
<span class="err"> '- 2011-12-13__watoki_tutorial.html</span>
</pre></div>
<p>That's pretty minimal (and ugly, visually). But it works and we can put it online and people can read it and that's what counts.</p>
<p>Now if I want to write another article, we'd have to</p>
<ol>
<li>copy the last article and change its content</li>
<li>add it to the <code>index.html</code></li>
</ol>
<p>The second step gets annoying pretty quickly especially if I forget to do it and then wonder why nobody reads about my newest epiphany. But we can use computer technology to fix this.</p>
<h2><a href="https://github.com/rtens/demo-blog/tree/e448998d9c562ec84d313e362fed0156a624c14d">PHP to the rescue</a></h2>
<p>(Did I mention that <em>watoki</em> is written in PHP? I hope you are not disappointed now that I didn't opt for a more trendy language. But PHP isn't actually half bad. So deal with it.)</p>
<p>It would be nice if we could just read the files in <code>articles</code> and print them as a list. In order to do so, we need an <code>index.php</code> to read the files and the <code>index.html</code> to print them.</p>
<div class="highlight"><pre><span></span># index.php
$articles = glob('articles/*.html');
include('index.html');
# index.html (excerpt)
<span class="cp"><?</span> <span class="k">foreach</span> <span class="p">(</span><span class="nv">$articles</span> <span class="k">as</span> <span class="nv">$article</span><span class="p">)</span> <span class="p">{</span> <span class="cp">?></span>
<span class="nt"><li><a</span> <span class="na">href=</span><span class="s">"</span><span class="cp"><?</span><span class="o">=</span> <span class="nv">$article</span> <span class="cp">?></span><span class="s">"</span><span class="nt">></span><span class="cp"><?</span><span class="o">=</span> <span class="nb">str_replace</span><span class="p">([</span><span class="s2">"_"</span><span class="p">,</span> <span class="s2">".html"</span><span class="p">],</span> <span class="s2">" "</span><span class="p">,</span> <span class="nb">basename</span><span class="p">(</span><span class="nv">$article</span><span class="p">));</span> <span class="cp">?></span><span class="nt"></li></span>
<span class="cp"><?</span> <span class="p">}</span> <span class="cp">?></span>
</pre></div>
<p>This is as ugly as it can be but it works and people can find and read articles without us having to update the list every time and that's what's important.</p>
<p>We can test it locally with the built-in web server of PHP. Just execute the following command in the project root and point your browser to <a href="http://localhost:8000"><code>http://localhost:8000</code></a>.</p>
<div class="highlight"><pre><span></span>$ php -S localhost:8000
</pre></div>
<p>I started with this as-simple-as-possible version because I want to demonstrate that a lot of times, you don't even need any library or much PHP code to build a minimal version of a product. Much can be faked for the sake of speed - at the cost of maintanance though.</p>
<h2><a href="https://github.com/rtens/demo-blog/tree/6035cca8dd7f1ca8f77662957571c109272ebf89">Getting rid of PHP</a></h2>
<p>After our last change, the front end designer of the project complains that he can't edit the HTML files any more because there are weird question marks and dollar symbols everywhere. So now we can either install PHP on his machine and teach him how to use it or we could think think of a smarter way to render a list dynamically. What if we could just write</p>
<div class="highlight"><pre><span></span># index.html
<span class="nt"><ul></span>
<span class="nt"><li><a</span> <span class="na">href=</span><span class="s">"articles/some_article.html"</span><span class="nt">></span>Date and Title of article<span class="nt"></a></li></span>
<span class="nt"></ul></span>
</pre></div>
<p>and some magical program would figure out that we want to repeat that <code>li</code> element for every article, filling out the hyperlink target and link caption as well. </p>
<p>Well, that's almost exactly what we're gonna do, except we have to give some hints to that program because it's not that magical after all. We do this with the <code>property</code> attribute.</p>
<div class="highlight"><pre><span></span># index.html
<span class="nt"><ul></span>
<span class="nt"><li</span> <span class="na">property=</span><span class="s">"article"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">property=</span><span class="s">"date"</span><span class="nt">></span>2011, December 13th<span class="nt"></span></span>
-
<span class="nt"><a</span> <span class="na">property=</span><span class="s">"link"</span> <span class="na">href=</span><span class="s">"articles/some_article.html"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">property=</span><span class="s">"title"</span><span class="nt">></span>Title of my article<span class="nt"></span></span>
<span class="nt"></a></span>
<span class="nt"></li></span>
<span class="nt"></ul></span>
</pre></div>
<p>That's some more HTML than before but it still renders as it should when the file is opened in a browser. In order to actually render our dynamic list, we need to install our first library: a rendering engine. There are two in <em>watoki</em> but the one that does the neat HTML trick is <a href="http://github.com/watoki/tempan">tempan</a> which is short for <em>Template Animation</em>. Installing it is a breeze thanks to <a href="http://getcomposer.org">composer</a>. Just open your favourite console at the project's root folder and execute the following command (make sure that <code>composer</code> is installed and in your <code>$PATH</code>)</p>
<div class="highlight"><pre><span></span>$ composer require watoki/tempan
</pre></div>
<p>And now we need to get our <code>index.php</code> to build a proper <em>View Model</em> (an array with keys matching the <code>property</code> values of the template) and render the template using <em>tempan</em></p>
<div class="highlight"><pre><span></span><span class="c1"># index.php</span>
<span class="n">require_once</span> <span class="s1">'vendor/autoload.php'</span><span class="p">;</span>
<span class="o">$</span><span class="n">viewModel</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'article'</span> <span class="o">=></span> <span class="n">assembleArticles</span><span class="p">()</span>
<span class="p">];</span>
<span class="o">$</span><span class="n">renderer</span> <span class="o">=</span> <span class="n">new</span> \<span class="n">watoki</span>\<span class="n">tempan</span>\<span class="n">Renderer</span><span class="p">(</span><span class="n">file_get_contents</span><span class="p">(</span><span class="s1">'index.html'</span><span class="p">));</span>
<span class="n">echo</span> <span class="o">$</span><span class="n">renderer</span><span class="o">-></span><span class="n">render</span><span class="p">(</span><span class="o">$</span><span class="n">viewModel</span><span class="p">);</span>
<span class="n">function</span> <span class="n">assembleArticles</span><span class="p">()</span> <span class="p">{</span>
<span class="o">$</span><span class="n">articles</span> <span class="o">=</span> <span class="p">[];</span>
<span class="n">foreach</span> <span class="p">(</span><span class="n">glob</span><span class="p">(</span><span class="s1">'articles/*.html'</span><span class="p">)</span> <span class="k">as</span> <span class="o">$</span><span class="n">article</span><span class="p">)</span> <span class="p">{</span>
<span class="n">list</span><span class="p">(</span><span class="o">$</span><span class="n">date</span><span class="p">,</span> <span class="o">$</span><span class="n">title</span><span class="p">)</span> <span class="o">=</span> <span class="n">explode</span><span class="p">(</span><span class="s1">'__'</span><span class="p">,</span> <span class="n">basename</span><span class="p">(</span><span class="o">$</span><span class="n">article</span><span class="p">));</span>
<span class="o">$</span><span class="n">articles</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'link'</span> <span class="o">=></span> <span class="n">array</span><span class="p">(</span><span class="s1">'href'</span> <span class="o">=></span> <span class="o">$</span><span class="n">article</span><span class="p">),</span>
<span class="s1">'date'</span> <span class="o">=></span> <span class="n">date</span><span class="p">(</span><span class="s1">'Y, F dS'</span><span class="p">,</span> <span class="n">strtotime</span><span class="p">(</span><span class="o">$</span><span class="n">date</span><span class="p">)),</span>
<span class="s1">'title'</span> <span class="o">=></span> <span class="n">str_replace</span><span class="p">([</span><span class="s1">'_'</span><span class="p">,</span> <span class="s1">'.html'</span><span class="p">],</span> <span class="s1">' '</span><span class="p">,</span> <span class="o">$</span><span class="n">title</span><span class="p">)</span>
<span class="p">];</span>
<span class="p">}</span>
<span class="k">return</span> <span class="o">$</span><span class="n">articles</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Now we feel a lot better since we separated logic from presentation. All data manipulation is now done by <code>index.php</code> and <code>index.html</code> contains nothing but mark-up description. Time to lean back and enjoy our beautiful code.</p>
<h2><a href="https://github.com/rtens/demo-blog/tree/55332545c10ecafa62b52d6e896c66962795c657">Cleaning up</a></h2>
<p>But soon the code doesn't look that beautiful any more, since it's all thrown together in one file. And it's also not at all testable. So let's structure it a bit better by putting the code in a class.</p>
<div class="highlight"><pre><span></span><span class="c1">#index.php</span>
<span class="n">require_once</span> <span class="s1">'vendor/autoload.php'</span><span class="p">;</span>
<span class="k">class</span> <span class="n">IndexResource</span> <span class="p">{</span>
<span class="n">public</span> <span class="n">function</span> <span class="n">respond</span><span class="p">()</span> <span class="p">{</span>
<span class="o">$</span><span class="n">renderer</span> <span class="o">=</span> <span class="n">new</span> \<span class="n">watoki</span>\<span class="n">tempan</span>\<span class="n">Renderer</span><span class="p">(</span><span class="n">file_get_contents</span><span class="p">(</span><span class="s1">'index.html'</span><span class="p">));</span>
<span class="k">return</span> <span class="o">$</span><span class="n">renderer</span><span class="o">-></span><span class="n">render</span><span class="p">([</span>
<span class="s1">'article'</span> <span class="o">=></span> <span class="o">$</span><span class="n">this</span><span class="o">-></span><span class="n">assembleArticles</span><span class="p">()</span>
<span class="p">]);</span>
<span class="p">}</span>
<span class="n">function</span> <span class="n">assembleArticles</span><span class="p">()</span> <span class="p">{</span>
<span class="o">//</span> <span class="o">...</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="o">$</span><span class="n">resource</span> <span class="o">=</span> <span class="n">new</span> <span class="n">IndexResource</span><span class="p">();</span>
<span class="n">echo</span> <span class="o">$</span><span class="n">resource</span><span class="o">-></span><span class="n">respond</span><span class="p">();</span>
</pre></div>
<p>and that class better lives in its own file of course. So here is our new folder structure</p>
<div class="highlight"><pre><span></span><span class="err">demo-blog</span>
<span class="err">|- index.php</span>
<span class="err">|- IndexResource.php</span>
<span class="err">|- index.html</span>
<span class="err">'- articles</span>
<span class="err">| |- ...</span>
<span class="err">'- ...</span>
</pre></div>
<h2><a href="https://github.com/rtens/demo-blog/tree/48859dd381168113589bd0025c9f6a7711984cad">Deliver it</a></h2>
<p>On their surface, web applications are all about getting a request to a resource and delivering the response back to the user. So let's use a web delivery library that handles most of it for us. The one provided by <em>watoki</em> is called <em><a href="http://github.com/watoki/curir">curir</a></em> (pronounced like "courier"). Again we can use composer to install it</p>
<div class="highlight"><pre><span></span>$ composer require watoki/curir
</pre></div>
<p>Now all we need to do is tell the <code>WebDelivery</code> to use the <code>IndexResource</code> as the root resource.</p>
<div class="highlight"><pre><span></span><span class="err">#index.php</span>
<span class="err">\watoki\curir\WebDelivery::quickResponse(IndexResource::class);</span>
</pre></div>
<p>If we run application now, it'll complain that <code>IndexResource</code> needs to implement <code>Responding</code>. So let's make sure that it does.</p>
<div class="highlight"><pre><span></span><span class="c1">#IndexResource.php</span>
<span class="k">class</span> <span class="n">IndexResource</span> <span class="n">implements</span> \<span class="n">watoki</span>\<span class="n">deli</span>\<span class="n">Responding</span> {
<span class="n">public</span> <span class="n">function</span> <span class="n">respond</span>(\<span class="n">watoki</span>\<span class="n">deli</span>\<span class="n">Request</span> <span class="nv">$r</span>) {
<span class="nv">$renderer</span> = <span class="nb">new</span> \<span class="n">watoki</span>\<span class="n">tempan</span>\<span class="n">Renderer</span>(<span class="n">file_get_contents</span>(<span class="s">'index.html'</span>));
<span class="k">return</span> <span class="nv">$renderer-</span>><span class="n">render</span>([
<span class="s">'article'</span> => <span class="nv">$this-</span>><span class="n">assembleArticles</span>()
]);
}
// ...
}
</pre></div>
<p>The <code>Responding</code> interface defines a method <code>respond</code> which receives a <code>Request</code> object from <em>curir</em>. We can use it to get information about the request, for example the request method or the value of a <code>page</code> parameter in case the list is paginated.</p>
<div class="highlight"><pre><span></span><span class="o">#</span><span class="n">IndexResource</span><span class="p">.</span><span class="n">php</span><span class="o">/</span><span class="n">IndexResource</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">respond</span><span class="p">(</span><span class="err">\</span><span class="n">watoki</span><span class="err">\</span><span class="n">deli</span><span class="err">\</span><span class="n">Request</span> <span class="err">$</span><span class="n">r</span><span class="p">)</span> <span class="err">{</span>
<span class="err">$</span><span class="k">method</span> <span class="o">=</span> <span class="err">$</span><span class="n">r</span><span class="o">-></span><span class="n">getMethod</span><span class="p">();</span>
<span class="err">$</span><span class="n">page</span> <span class="o">=</span> <span class="err">$</span><span class="n">r</span><span class="o">-></span><span class="n">getArguments</span><span class="p">()</span><span class="o">-></span><span class="k">get</span><span class="p">(</span><span class="s1">'page'</span><span class="p">);</span>
<span class="o">//</span> <span class="p">...</span>
<span class="err">}</span>
</pre></div>
<h2><a href="https://github.com/rtens/demo-blog/tree/da0fcf69f1b5580c64ce9f8dfbc4b0d29a144018">Easier Delivery</a></h2>
<p>But since resources almost always respond to a certain method with certain parameters and then render a template using structured data, <em>curir</em> provides an easier way to do that. By extending <code>Container</code>, we can replace the <code>respond</code> method with the following</p>
<div class="highlight"><pre><span></span><span class="c1">#IndexResource.php</span>
<span class="k">class</span> <span class="n">IndexResource</span> <span class="k">extends</span> \<span class="n">watoki</span>\<span class="n">curir</span>\<span class="n">Container</span> <span class="p">{</span>
<span class="n">public</span> <span class="n">function</span> <span class="n">doGet</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">[</span>
<span class="s1">'article'</span> <span class="o">=></span> <span class="o">$</span><span class="n">this</span><span class="o">-></span><span class="n">assembleArticles</span><span class="p">()</span>
<span class="p">];</span>
<span class="p">}</span>
<span class="o">//</span> <span class="o">...</span>
<span class="p">}</span>
</pre></div>
<p><em>curir</em> maps the request to a resource to a method named <code>do<HTTP_METHOD></code> and the returned value is used as data for the renderer which uses a file with the same name as the resource as template (in this case <code>index.html</code>). The default renderer is the <code>PhpRenderer</code> so we need to tell curir to use <em>tempan</em>.</p>
<div class="highlight"><pre><span></span><span class="err">#index.php</span>
<span class="err">$factory = WebDelivery::init(new TempanRenderer());</span>
<span class="c">WebDelivery::quickResponse(IndexResource::class, $factory);</span>
</pre></div>
<h2><a href="https://github.com/rtens/demo-blog/tree/cc8b8159c946ec4a79224fb051eeac78921ad6bb">Talk to me</a></h2>
<p>The blog is a roaring success and tons of people read it but more and more would like to be able to comment on the articles. So we add a comment form to each article and point it to the <code>index.php</code>.</p>
<div class="highlight"><pre><span></span>#2011-12-13__watoki_tutorial.html
<span class="nt"><hr></span>
<span class="nt"><h3></span>Leave a comment<span class="nt"></h3></span>
<span class="nt"><form</span> <span class="na">method=</span><span class="s">"post"</span> <span class="na">action=</span><span class="s">"../index.php"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"hidden"</span> <span class="na">name=</span><span class="s">"article"</span> <span class="na">value=</span><span class="s">"watoki tutorial"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">name=</span><span class="s">"email"</span> <span class="na">placeholder=</span><span class="s">"Your Email"</span><span class="nt">><br></span>
<span class="nt"><textarea</span> <span class="na">name=</span><span class="s">"comment"</span><span class="nt">></textarea><br></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"submit"</span><span class="nt">></span>
<span class="nt"></form></span>
</pre></div>
<p>If we just try to submit that form, we'll get an error page saying "Error: 405 Method Not Allowed" and clicking on the <em>details</em> link reveals that "Method [doPost] does not exist in [IndexResource]". So let's add it.</p>
<div class="highlight"><pre><span></span><span class="o">#</span><span class="n">IndexResource</span><span class="p">.</span><span class="n">php</span><span class="o">/</span><span class="n">IndexResource</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">doPost</span><span class="p">()</span> <span class="err">{</span>
<span class="k">return</span> <span class="n">array_merge</span><span class="p">(</span><span class="err">$</span><span class="n">this</span><span class="o">-></span><span class="n">doGet</span><span class="p">(),</span> <span class="p">[</span>
<span class="ss">"message"</span> <span class="o">=></span> <span class="ss">"Thanks for your comment. I'll publish it soon."</span>
<span class="p">]);</span>
<span class="err">}</span>
</pre></div>
<p>This works, but we don't see the message yet because we need to add it to the template. Let's put it into the sub-header.</p>
<div class="highlight"><pre><span></span>#index.html
<span class="nt"><h4</span> <span class="na">property=</span><span class="s">"message"</span><span class="nt">></span>[...]<span class="nt"></h4></span>
</pre></div>
<p>If we now would like to email the comment to ourself, we need to access the submitted data. Since <em>curir</em> maps the request parameter to the method signature, we can simply do this:</p>
<div class="highlight"><pre><span></span><span class="n">#IndexResource</span><span class="p">.</span><span class="n">php</span><span class="o">/</span><span class="n">IndexResource</span><span class="w"></span>
<span class="k">public</span><span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">doPost</span><span class="p">(</span><span class="err">$</span><span class="n">article</span><span class="p">,</span><span class="w"> </span><span class="err">$</span><span class="n">email</span><span class="p">,</span><span class="w"> </span><span class="err">$</span><span class="n">comment</span><span class="p">)</span><span class="w"> </span><span class="err">{</span><span class="w"></span>
<span class="w"> </span><span class="n">mail</span><span class="p">(</span><span class="ss">"me@example.com"</span><span class="p">,</span><span class="w"> </span><span class="ss">"New comment on $article"</span><span class="p">,</span><span class="w"> </span><span class="err">$</span><span class="n">comment</span><span class="p">,</span><span class="w"> </span><span class="ss">"From: $email"</span><span class="p">);</span><span class="w"></span>
<span class="w"> </span><span class="o">//</span><span class="w"> </span><span class="p">...</span><span class="w"></span>
<span class="err">}</span><span class="w"></span>
</pre></div>
<h2><a href="https://github.com/rtens/demo-blog/tree/23a34b25647c114adfb5f2db2753fbcacce99b89">Dynamic Articles</a></h2>
<p>The comments work great but we receive so many that adding them to each article quickly turns into a bottle neck. We want to be able to show them automatically and while we're at it, use a template for the articles so we don't have to copy the entire page for each new article. There is only one solution: articles need to become dynamic resources.</p>
<p>The first step is to strip the article files of all non-content HTML and put that into a template.</p>
<div class="highlight"><pre><span></span>#article.html
<span class="nt"><a</span> <span class="na">href=</span><span class="s">"index.php"</span><span class="nt">></span>Overview<span class="nt"></a></span>
<span class="nt"><h1</span> <span class="na">property=</span><span class="s">"title"</span><span class="nt">></span>Building Web Applications with watoki<span class="nt"></h1></span>
<span class="nt"><h4</span> <span class="na">property=</span><span class="s">"date"</span><span class="nt">></span>Tue 13 December 2011<span class="nt"></h4></span>
<span class="nt"><div</span> <span class="na">property=</span><span class="s">"content"</span><span class="nt">></span>Here be content<span class="nt"></div></span>
<span class="nt"><hr></span>
<span class="nt"><h3></span>Leave a comment<span class="nt"></h3></span>
<span class="nt"><form</span> <span class="na">method=</span><span class="s">"post"</span> <span class="na">action=</span><span class="s">"index.php"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">property=</span><span class="s">"commentOn"</span> <span class="na">type=</span><span class="s">"hidden"</span> <span class="na">name=</span><span class="s">"article"</span> <span class="na">value=</span><span class="s">"watoki tutorial"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">name=</span><span class="s">"email"</span> <span class="na">placeholder=</span><span class="s">"Your Email"</span><span class="nt">><br></span>
<span class="nt"><textarea</span> <span class="na">name=</span><span class="s">"comment"</span><span class="nt">></textarea><br></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"submit"</span><span class="nt">></span>
<span class="nt"></form></span>
</pre></div>
<p>The second step is to create a corresponding resource class with a <code>doGet</code> method.</p>
<div class="highlight"><pre><span></span><span class="c1">#ArticleResource.php</span>
<span class="k">class</span> <span class="n">ArticleResource</span> <span class="k">extends</span> \<span class="n">watoki</span>\<span class="n">curir</span>\<span class="n">Resource</span> <span class="p">{</span>
<span class="n">public</span> <span class="n">function</span> <span class="n">doGet</span><span class="p">(</span><span class="o">$</span><span class="n">article</span><span class="p">)</span> <span class="p">{</span>
<span class="n">list</span><span class="p">(</span><span class="o">$</span><span class="n">date</span><span class="p">,</span> <span class="o">$</span><span class="n">title</span><span class="p">)</span> <span class="o">=</span> <span class="n">explode</span><span class="p">(</span><span class="s1">'__'</span><span class="p">,</span> <span class="o">$</span><span class="n">article</span><span class="p">);</span>
<span class="k">return</span> <span class="p">[</span>
<span class="s1">'title'</span> <span class="o">=></span> <span class="n">ucfirst</span><span class="p">(</span><span class="n">str_replace</span><span class="p">(</span><span class="s1">'_'</span><span class="p">,</span> <span class="s1">' '</span><span class="p">,</span> <span class="o">$</span><span class="n">title</span><span class="p">)),</span>
<span class="s1">'date'</span> <span class="o">=></span> <span class="n">date</span><span class="p">(</span><span class="s1">'Y, F dS'</span><span class="p">,</span> <span class="n">strtotime</span><span class="p">(</span><span class="o">$</span><span class="n">date</span><span class="p">)),</span>
<span class="s1">'content'</span> <span class="o">=></span> <span class="n">file_get_contents</span><span class="p">(</span><span class="s2">"articles/$article.html"</span><span class="p">),</span>
<span class="s1">'commentOn'</span> <span class="o">=></span> <span class="p">[</span><span class="s1">'value'</span> <span class="o">=></span> <span class="o">$</span><span class="n">article</span><span class="p">]</span>
<span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>The last thing we need to do is adapt the links in the overview list so they point to the new resource, e.g. <code>article.html?article=2011-12-13__watoki_tutorial</code>.</p>
<div class="highlight"><pre><span></span><span class="o">#</span><span class="n">IndexResource</span><span class="p">.</span><span class="n">php</span><span class="o">/</span><span class="n">IndexResource</span><span class="p">::</span><span class="n">assembleArticle</span><span class="p">()</span>
<span class="k">return</span> <span class="p">[</span>
<span class="s1">'link'</span> <span class="o">=></span> <span class="nb">array</span><span class="p">(</span><span class="s1">'href'</span> <span class="o">=></span> <span class="s1">'article.html?article='</span> <span class="p">.</span> <span class="n">substr</span><span class="p">(</span><span class="n">basename</span><span class="p">(</span><span class="err">$</span><span class="n">articleFile</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">5</span><span class="p">)),</span>
<span class="s1">'date'</span> <span class="o">=></span> <span class="nb">date</span><span class="p">(</span><span class="s1">'Y, F dS'</span><span class="p">,</span> <span class="n">strtotime</span><span class="p">(</span><span class="err">$</span><span class="nb">date</span><span class="p">)),</span>
<span class="s1">'title'</span> <span class="o">=></span> <span class="n">str_replace</span><span class="p">([</span><span class="s1">'_'</span><span class="p">,</span> <span class="s1">'.html'</span><span class="p">],</span> <span class="s1">' '</span><span class="p">,</span> <span class="err">$</span><span class="n">title</span><span class="p">)</span>
<span class="p">];</span>
</pre></div>
<p>Lastly, we need to put <code>WebDelivery</code> in charge of all requests so it can them to the dynamic resources. We can do this by passing <code>index.php</code> to the web server as "routing file" (or using <code>mod_rewrite</code> with <em>Apache</em>).</p>
<div class="highlight"><pre><span></span>$ php -S localhost:8000 index.php
</pre></div>
<p>To keep this tutorial short, I'm not gonna describe how to display the comments, but you can find it in the <a href="https://github.com/rtens/demo-blog/tree/84e01ef1e1fa8909275301165c40509c4be2032c">source code</a> or try to do it as an exercise.</p>
<h2><a href="https://github.com/rtens/demo-blog/tree/5137eadc067f04bd01e42a79a706006d9371f26d">Link Reanimation</a></h2>
<p>Everything seems to be working well until we realise that all links to our articles that we sent to our friends and proudly tweeted about are now broken. Because articles now have the URLs <code>article.html?article=foo</code> instead of <code>articles/foo.html</code>. We have to find a way to map the latter to the former.</p>
<p>As almost always, there are multiple ways to achieve one goal. For example we could do the re-routing on web server level (e.g. with <code>mod_rewrite</code>) but let's say that we want to do it in the application so we can stay environment-independent.</p>
<p>A design goal in all the <em>watoki</em> libraries was to avoid "magic" without compromising convenience. This is achieved by always keeping things <em>discoverable</em> but offering short-cuts for the most common use cases. This of course works best if you are using an IDE that supports code navigation (like <a href="https://www.jetbrains.com/phpstorm/">PhpStorm</a> - sorry Sublimers) so you can jump to a symbol definition by simply clicking on it. </p>
<p>You can use the following approach for answering most questions of the form "How can I change X?" in all libraries of <em>watoki</em>. I suggest that, while reading the following explanation, to try retracing the described paths in the actual code.</p>
<p>That said, let's try to find out how <em>curir</em> routes requests so we can change it. We made sure that all requests are handled by <code>index.php</code> where we call <code>WebDelivery::quickResponse()</code>, but what happens next? With a little digging, we'll find that the call leads to the following code being executed.</p>
<div class="highlight"><pre><span></span><span class="p">#</span><span class="nn">WebDelivery</span><span class="p">.</span><span class="nc">php</span><span class="o">/</span><span class="nt">WebDelivery</span><span class="p">::</span><span class="nd">quickResponse</span> <span class="o">(</span><span class="nt">in-lined</span> <span class="o">&</span> <span class="nt">simplified</span><span class="o">)</span>
<span class="o">$</span><span class="nt">router</span> <span class="o">=</span> <span class="nt">new</span> <span class="nt">NoneRouter</span><span class="o">(</span><span class="nt">RespondingTarget</span><span class="p">::</span><span class="nd">factory</span><span class="o">($</span><span class="nt">root</span><span class="o">));</span>
<span class="o">$</span><span class="nt">builder</span> <span class="o">=</span> <span class="nt">new</span> <span class="nt">WebRequestBuilder</span><span class="o">(</span><span class="nt">new</span> <span class="nt">WebEnvironment</span><span class="o">($</span><span class="nt">_SERVER</span><span class="o">,</span> <span class="o">$</span><span class="nt">_REQUEST</span><span class="o">,</span> <span class="o">$</span><span class="nt">_FILES</span><span class="o">));</span>
<span class="o">$</span><span class="nt">deliverer</span> <span class="o">=</span> <span class="nt">new</span> <span class="nt">WebResponseDeliverer</span><span class="o">();</span>
<span class="o">$</span><span class="nt">delivery</span> <span class="o">=</span> <span class="nt">new</span> <span class="nt">WebDelivery</span><span class="o">($</span><span class="nt">router</span><span class="o">,</span> <span class="o">$</span><span class="nt">builder</span><span class="o">,</span> <span class="o">$</span><span class="nt">deliverer</span><span class="o">);</span>
<span class="o">$</span><span class="nt">delivery-</span><span class="o">></span><span class="nt">run</span><span class="o">();</span>
</pre></div>
<p>The <code>WebDelivery</code> is instantiated with a <code>Router</code>, a <code>RequestBuilder</code> and a <code>ResponseDeliverer</code>, so a request is built, routed to its target, and the response delivered. The router is this case does nothing (hence <strong>None</strong>Router) and its target is a <code>RespondingTarget</code> whose <code>respond()</code> method simply invokes the <code>respond()</code> method of the <em>root</em> resource, in our case <code>IndexResource</code>. So in order to change the routing behaviour, we could exchange that <code>NoneRouter</code> with our own, configured version. By looking at sub-classes of <code>Router</code> we see a class called <code>DynamicRouter</code> which turns out to be just what we need. The result would look like this.</p>
<div class="highlight"><pre><span></span><span class="p">#</span><span class="nn">index</span><span class="p">.</span><span class="nc">php</span>
<span class="o">$</span><span class="nt">factory</span> <span class="o">=</span> <span class="nt">WebDelivery</span><span class="p">::</span><span class="nd">init</span><span class="o">(</span><span class="nt">new</span> <span class="nt">TempanRenderer</span><span class="o">());</span>
<span class="o">$</span><span class="nt">router</span> <span class="o">=</span> <span class="nt">new</span> <span class="err">\</span><span class="nt">watoki</span><span class="err">\</span><span class="nt">deli</span><span class="err">\</span><span class="nt">router</span><span class="err">\</span><span class="nt">DynamicRouter</span><span class="o">();</span>
<span class="o">$</span><span class="nt">router-</span><span class="o">></span><span class="nt">addObjectPath</span><span class="o">(</span><span class="s1">'articles/{article}'</span><span class="o">,</span> <span class="nt">ArticleResource</span><span class="p">::</span><span class="nd">class</span><span class="o">,</span> <span class="o">$</span><span class="nt">factory</span><span class="o">);</span>
<span class="o">$</span><span class="nt">router-</span><span class="o">></span><span class="nt">addObjectPath</span><span class="o">(</span><span class="s1">''</span><span class="o">,</span> <span class="nt">IndexResource</span><span class="p">::</span><span class="nd">class</span><span class="o">,</span> <span class="o">$</span><span class="nt">factory</span><span class="o">);</span>
<span class="nt">WebDelivery</span><span class="p">::</span><span class="nd">quickRoute</span><span class="o">($</span><span class="nt">router</span><span class="o">,</span> <span class="o">$</span><span class="nt">factory</span><span class="o">);</span>
</pre></div>
<p>This works! But of course there is also another way (which is usually easier and also more flexible). With a little more digging we find out, that the <code>respond()</code> method of <code>IndexResource</code> is inherited by <code>Container</code> which again, uses its own router to find the target of the request. So if every <code>Container</code> has its own <code>Router</code>, we can just extend that a little and don't have to overwrite the global router of <code>WebDelivery</code>. All we need to do is overwrite the <code>createRouter()</code> method.</p>
<div class="highlight"><pre><span></span><span class="p">#</span><span class="nn">IndexResource</span><span class="p">.</span><span class="nc">php</span><span class="o">/</span><span class="nt">IndexResource</span>
<span class="nt">protected</span> <span class="nt">function</span> <span class="nt">createRouter</span><span class="o">()</span> <span class="p">{</span>
<span class="err">$router</span> <span class="err">=</span> <span class="err">new</span> <span class="err">\watoki\deli\router\DynamicRouter()</span><span class="p">;</span>
<span class="err">$router->addObjectPath('articles/{article</span><span class="p">}</span><span class="err">'</span><span class="o">,</span> <span class="nt">ArticleResource</span><span class="p">::</span><span class="nd">class</span><span class="o">,</span> <span class="o">$</span><span class="nt">this-</span><span class="o">></span><span class="nt">factory</span><span class="o">);</span>
<span class="nt">return</span> <span class="nt">new</span> <span class="nt">MultiRouter</span><span class="o">(</span><span class="cp">[</span><span class="nv">$router</span><span class="p">,</span> <span class="k">parent</span><span class="nl">::createRouter</span><span class="p">()</span><span class="cp">]</span><span class="o">);</span>
<span class="err">}</span>
</pre></div>
<h2><a href="https://github.com/rtens/demo-blog/tree/88824984e45008e4342c7132a95d93ed6c685d6b">Article Not Found</a></h2>
<p>All our URLs work again and we're fairly happy with the whole thing. But we discover one rather annoying thing: If we now try to browse to an article that doesn't exist (e.g. <a href="http://localhost:8000/articles/foo"><code>articles/foo</code></a>), we get a weird empty article instead of the "File Not Found" error we would expect. So let's fix that.</p>
<div class="highlight"><pre><span></span><span class="o">#</span><span class="n">ArticleResource</span><span class="p">.</span><span class="n">php</span><span class="o">/</span><span class="n">ArticleResource</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">doGet</span><span class="p">(</span><span class="err">$</span><span class="n">article</span><span class="p">)</span> <span class="err">{</span>
<span class="err">$</span><span class="n">file</span> <span class="o">=</span> <span class="ss">"articles/$article.html"</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">file_exists</span><span class="p">(</span><span class="err">$</span><span class="n">file</span><span class="p">))</span> <span class="err">{</span>
<span class="n">throw</span> <span class="k">new</span> <span class="k">Exception</span><span class="p">(</span><span class="ss">"The article [$article] does not exist."</span><span class="p">);</span>
<span class="err">}</span>
<span class="o">//</span> <span class="p">...</span>
<span class="err">}</span>
</pre></div>
<p>Now we get an "500 Internal Server Error" since <em>curir</em> catches all errors (including fatal ones) and exceptions and turns them into server errors. In order to generate other HTTP status codes and custom messages we can throw an <code>HttpError</code> instead.</p>
<div class="highlight"><pre><span></span><span class="err">throw new HttpError(WebResponse::STATUS_NOT_FOUND, "The article [$article] does not exist.");</span>
</pre></div>
<h2>Le Fin</h2>
<p>So this is how you build a basic web application with <em><a href="http://github.com/watoki">watoki</a></em>, or more precisely with <em><a href="http://github.com/watoki/curir">curir</a></em> and <em><a href="http://github.com/watoki/tempan">tempan</a></em>. Of course this tutorial only covers a tiny part of the mentioned libraries and an even smaller part of the whole tool kit. So if you would like to give any of these libraries a try or have any comment or feedback, just drop me a line. I always appreciate any feedback.</p>Tool Tyranny2014-10-15T00:00:00+02:002014-10-15T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2014-10-15:/tool-tyranny.html<p>So Richard McIntyre (aka <a href="https://twitter.com/mackstar">mackstar</a>) created a BDD tool named <a href="https://github.com/bbc-sport/ShouldIT/">ShouldIT</a> (<a href="https://skillsmatter.com/skillscasts/5675-should-it-a-new-approach-to-bdd-pain-not-included">video</a>) which led to a discussion between him and Konstantin Kudryashov (aka <a href="https://twitter.com/everzet">everzet</a>), mostly comparing ShouldIT to Cucumber/Behat. For example in <a href="https://gist.github.com/icambridge/7694d6d7b0a987f6c33b">this gist</a>.</p>
<p>Guess I'm jumping kinda late on the bandwagon here but I wanted to add my …</p><p>So Richard McIntyre (aka <a href="https://twitter.com/mackstar">mackstar</a>) created a BDD tool named <a href="https://github.com/bbc-sport/ShouldIT/">ShouldIT</a> (<a href="https://skillsmatter.com/skillscasts/5675-should-it-a-new-approach-to-bdd-pain-not-included">video</a>) which led to a discussion between him and Konstantin Kudryashov (aka <a href="https://twitter.com/everzet">everzet</a>), mostly comparing ShouldIT to Cucumber/Behat. For example in <a href="https://gist.github.com/icambridge/7694d6d7b0a987f6c33b">this gist</a>.</p>
<p>Guess I'm jumping kinda late on the bandwagon here but I wanted to add my two cents.</p>
<p>To me it seems like the discussion is mostly about formularization and structure. While everzet's approach leads to a more detailed description of examples by explicitly describing the context for each scenario, mackstar prefers to combine the contexts (I guess mostly to avoid repetition?) and just formulate expectations explicitly.</p>
<p>Both approaches have something fundamental in common: using examples to specify the behaviour of a system. The difference is only <em>how</em> these example are formulated. But to me that's an "implementation detail".</p>
<p>The more important difference between Behat/Cucumber and ShouldIT is the direction of connecting the description and the implementation of the examples. While Cucumber executes the description (the .feature file) and matches its steps to the code, ShouldIT does it exactly the other way around - executing the code and then amatches the results to the descriptions.</p>
<p>So the discussion is not about the differences of the tools as much as about different description styles. It seems though as if the tools and the styles are all tangled up.</p>
<p>But what I don't understand is <em>why</em> a tool would ever dictate a certain style. Shouldn't the style and struct ure be up to the user? I sort of understand it in Cucumber's case because it needs to parse the description. But I don't see why ShouldIT couldn't work with just any style. After all it's just matching test results to text.</p>
<p>My approach is just not to use any tool for writing and executing the specification (besides a test runner, in my case PHPUnit). By only relying on the code, I have complete freedom over style and structure. This approach also avoids the duplication created by the separation of description and implementation.</p>
<p>But since (PHP) code is super ugly I <em>do</em> use a tool for browsing and presentation of the specification named <a href="http://dox.rtens.org">dox</a>, which I wrote about in <a href="http://blog.rtens.org/specification-by-example.html">my last article</a>.</p>Specification by Example2014-09-11T00:00:00+02:002014-09-11T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2014-09-11:/specification-by-example.html<p>In a <a href="http://blog.rtens.org/polyamorous-tdd.html">previous post</a> I argued against a testing monoculture and suggested to mix tests with different levels of integration. Since UI tests cannot test the system completey, but unit tests are often times too fine-grained to justify their investment, staying away from these extremes is often times the best …</p><p>In a <a href="http://blog.rtens.org/polyamorous-tdd.html">previous post</a> I argued against a testing monoculture and suggested to mix tests with different levels of integration. Since UI tests cannot test the system completey, but unit tests are often times too fine-grained to justify their investment, staying away from these extremes is often times the best solution. I called this strategy <em>Daedalus Testing</em>.</p>
<p>I've been using this approach for a while now and also <a href="http://blog.rtens.org/category/talks.html">talked about it</a> at several conferences so I thought it's time to write down how I implement the approach and which tools I use.</p>
<h2>TDD vs BDD</h2>
<p>In the majority of articles I read about <em>Test-Driven Development</em>, the author uses it as a synonym with <em>Unit Testing</em>, ignoring that any testing strategy can be applied in a test-driven manner. It seems to me that almost always when people get <a href="http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html">frustrated about TDD</a>, they are actually frustrated about unit testing. </p>
<p>I agree with <a href="https://twitter.com/searls">Justin Searls</a> who argues that this frustration emerges mostly from <a href="http://blog.testdouble.com/posts/2014-01-25-the-failures-of-intro-to-tdd.html"><em>The Failures of "Intro to TDD"</em></a> and the false promise that unit-level TDD automatically leads to better design. So when we teach test-driven developing practice, we must be careful to not limit it to unit testing but enable writing automated test on every level of abstraction and with any amount of integration.</p>
<p><img src="static/img/test_stack.png"/></p>
<h2>Description Levels</h2>
<p>The first question, I ask myself when I start with a new system is "What do I want to specify first?", which leads to "What part of the system should I build first?", which should be answered by "What has the biggest value?".</p>
<p>If the purpose of the system is to automate a process, then the most important part are probably the <strong>business rules</strong>. In this case, the specification should be on the level of the business logic and use the language of the process. This naturally leads to a system design where the business logic is encapsulated into something - call it <a href="http://www.youtube.com/watch?v=WpkDN78P884">interactors</a> or [use-cases service]. The architecture of the production system is actually secondary. The important thing is that the behaviour of the business logic is not described on the user interface level, nor on the class/unit level but on the business process level.</p>
<p>Unless of course it's the behaviour of the <strong>user interface</strong> you would like to specify. This is usually very hard for me since often times user interface have a lot of "soft" specifications, like "it needs to feel snappy", "it needs to look consistent", and "it needs to be pleasent to the eye". I have yet to find a way to describe these requirements in a language that the computer understands. Instead I <a href="http://blog.rtens.org/codemotion-2013.html">make it really easy</a> to test my HTML templates manually. But sometimes there is actually logic in the UI worth an automated test. This test but only this test should be written using UI concepts like forms and clicking buttons.</p>
<p>Or maybe I already have a system and it's a <strong>sub-system</strong> or just a <strong>single class</strong> whose behaviour I would like to specify. This is when I can do do my old fashioned unit-testing and use concepts like exceptions and method calls in my test.</p>
<p>I rarely ever use full-stack HTTP-level <strong>integration</strong> tests so I don't have any guidelines for those yet.</p>
<p>Each level of abstraction targets a different kind of stake holder and uses a different language with different concepts, but should be consistent within their boundaries. The automated tests are also usually implemented using different technologies. I usually start on the level of the business domain and move up to a more integrational level if I need more confidence and down to a more unit-level if I need to locate a bug or implement a complicated algorithm.</p>
<h2>Test Literacy</h2>
<p>So now that you have nice automated tests make sure that people can read them. I've heard a lot that "tests document the production system" and I'm convinced that it's true but only under the condition that you can understand the test. Any maybe that's just me, but reading code is hard (and also no fun). And even more important maybe, there are a lot of people who are not even able to read code. Think of the business stake holders. They should be part of formulating the specification of a system as well. Especially when they are about business logic.</p>
<p>So let's not use code to describe the test cases but a natural language that everybody, not just technical people, can understand - an <strong>ubiquitous language</strong>. If we normalize the language's structure just a bit, we can still implement it and execute it automatically. This strategy is commonly known as <a href="http://dannorth.net/introducing-bdd/">Behaviour-Driven Development</a>. But since the semantic delusion of that term has reached a point where it means anything and nothing, I'm gonna use <a href="http://specificationbyexample.com/">Specification by Example (SbE)</a> instead.</p>
<p>The idea of SbE is to describe the behaviour of any system with <em>examples</em>. These examples are written collaboratively in a way that <em>all</em> stake holders can understand. They are then implemented as automated tests without changing the original formulation of the example. This way they can serve as specficiation, validation and documentation of any software system.</p>
<p>These examples can be formulated in any way and still be implementable. But it helps to have some structure so I usually use a <a href="https://github.com/cucumber/cucumber/wiki/Gherkin">gherkin</a>-ish syntax with <em>given</em>, <em>when</em> and <em>then</em> but it works just as well with the <em>describe-context-it</em> structure of <a href="http://rspec.info/">rspec</a> and its relatives.</p>
<p>So instead of</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">testIsDeliveryFree</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">customer</span> <span class="o">=</span> <span class="n">Customer</span><span class="p">()</span>
<span class="n">customer</span><span class="o">.</span><span class="n">setVip</span><span class="p">(</span><span class="n">true</span><span class="p">)</span>
<span class="n">basket</span> <span class="o">=</span> <span class="n">Basket</span><span class="p">()</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="n">basket</span><span class="o">.</span><span class="n">getItems</span><span class="p">()</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">Book</span><span class="p">())</span>
<span class="n">delivery</span> <span class="o">=</span> <span class="n">DeliveryManager</span><span class="p">(</span><span class="n">customer</span><span class="p">,</span> <span class="n">basket</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">assertTrue</span><span class="p">(</span><span class="n">delivery</span><span class="o">.</span><span class="n">isDeliveryFree</span><span class="p">())</span>
</pre></div>
<p>you can write</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">scenarioVipWithFiveBooksShouldBeFree</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">givenIAmAVipCustomer</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">givenIHave_BooksInMyBasket</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">whenICheckMyDeliveryOptions</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">thenTheDeliveryShouldBeFree</span><span class="p">()</span>
</pre></div>
<h2>Make it accessible</h2>
<p>Now that we have nice abstractionally-bounded specifications, implemented as automated tests and written in an ubiquitous language using examples we need a way that people can find them. Of course there are in the code base but first of all, they are still (although very niceley readable) code and second of all, not everybody is confortable with browsing through a code base.</p>
<p>So we need a way to browse the specifications comfortably and have them presented in an easy-to-read form. The approach of <a href="http://cukes.info/">cucumber</a> and <a href="http://behat.org">its sorts</a> is to write the specification in plain text files and match them with code fragments when run. But for me this simply causes too much duplication and it's also one more language with yet another syntax and its own quirks and (usually) no support for code navigation and refactoring. </p>
<p>As I've shown above, all you need is a simple <em>method extraction</em> to put this ugly test code into easily understandable methods with natural-language names. It's really all it takes. The mentioned tools argue with increasing the readability of the tests since they are not written in code but in my experience the gain is marginal at best.</p>
<p>If tests are really to play the role of documenation, they also need to be <em>accessible for everyone</em>. The code repository is not neccesarily the most accessible place for business stake holders. What they usually ask for is a PDF of HTML file they can browse and read easily. So why not export the test code to a browsable web page?</p>
<p>Born was <em><a href="http://dox.rtens.org">dox</a></em>, a browser for executable documentation. It parses the test classes, their methods, code and comments and creates HTML pages that you can browse and read. Comments are parsed as well so the can contain HTML or other mark-up languages like <a href="http://daringfireball.net/projects/markdown/">markdown</a> in order to create beautiful living documentation. <em>dox</em> also processes test reports and indicates the status of each scenario with colors. This way you can easily see how many scenarios are already implemented and which ones are failing.</p>
<p><img src="static/img/dox_diagram.png"/></p>
<p>Just check out dox's <a href="http://dox.rtens.org/projects/rtens-dox/specs/Introduction">documentation</a> to learn more about it or <a href="https://twitter.com/rtens_">drop me a line</a> if you would like to try it for you project.</p>FrOSCon 20142014-08-24T00:00:00+02:002014-08-24T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2014-08-24:/froscon-2014.html<p>I was invited at this years <a href="https://www.froscon.de">FrOSCon</a> to speak about executable documentation which is sort of follow-up to <a href="http://blog.rtens.org/froscon-2013.html">last year</a> where I spoke about <a href="http://specificationbyexample.com/">Specficiation by Example</a> (aka Behavior-Driven Development) and how to use automated tests to create a self-validating documentation of a software application. This year I approached the …</p><p>I was invited at this years <a href="https://www.froscon.de">FrOSCon</a> to speak about executable documentation which is sort of follow-up to <a href="http://blog.rtens.org/froscon-2013.html">last year</a> where I spoke about <a href="http://specificationbyexample.com/">Specficiation by Example</a> (aka Behavior-Driven Development) and how to use automated tests to create a self-validating documentation of a software application. This year I approached the matter from the documentation side, transforming the documentation of <a href="http://github.com/rtens/mockster">mockster</a> into an executable program (aka automated tests).</p>
<p><a href="/res/executable_documentation_slides.pdf">You can find the slides here</a>. And for the first time, there is also a <a href="https://www.youtube.com/watch?v=5j42QvDMCjg">video of this talk</a> availble.</p>
<p>Anyway, I enjoyed a lot giving the talk, thanks to a very interested and engaging people listing who also gave <a href="https://twitter.com/raulfraile/status/503541717006835713">some</a> nice <a href="https://twitter.com/gobilo/status/503607248447602689">feedback</a>. Thanks for that. I'm already looking forward to FrOSCon 2015.</p>Polyamorous TDD2014-04-26T00:00:00+02:002014-04-26T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2014-04-26:/polyamorous-tdd.html<p>Three things happened during the last week that each increased my urge to write this article. The coincidence is almost uncanny.</p>
<ul>
<li>Monday: over the easter weekend I finally built a tool I've been meaning to build for over a year.</li>
<li>Tuesday: I became responsible for releasing and quality of my …</li></ul><p>Three things happened during the last week that each increased my urge to write this article. The coincidence is almost uncanny.</p>
<ul>
<li>Monday: over the easter weekend I finally built a tool I've been meaning to build for over a year.</li>
<li>Tuesday: I became responsible for releasing and quality of my first <a href="http://rubyonrails.org/">Ruby on Rails</a> project.</li>
<li>Wednesday: <a href="http://david.heinemeierhansson.com/">David Heinemeier Hansson</a> wrote a <a href="http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html">controversial article</a> about <a href="http://c2.com/cgi/wiki?TestDrivenDevelopment">TDD</a></li>
</ul>
<p>The connections between these events are actually circular. </p>
<ul>
<li>The tool is part of a management method that I will employ in the Rails project. </li>
<li>David happens to be the creator of Rails.</li>
<li>Both the tool and the management method evolve around automated tests and tackle precisely the problem David seems to have with TDD.</li>
</ul>
<p>Each of these events deserves it's own article. So I'll concentrate in this one on my point of view concerning the discussion that spun around David's article.</p>
<h2>Programming & Life Styles</h2>
<p><a href="http://en.wikipedia.org/wiki/Robert_Cecil_Martin">Robert Martin</a> responded to David with an article he titled <em><a href="http://blog.8thlight.com/uncle-bob/2014/04/25/MonogamousTDD.html">Monogamous TDD</a></em> in which he compares TDD with monogamy, contrasting it with David's analogy <em>"Test-first fundamentalism is like abstinence-only sex ed"</em>.</p>
<p>I like the metaphor. Like abstinence or monogamy, TDD is <em>choice</em> of style. And for some, strict TDD probably feels like abstinence. Unintuitive, unnatrual, morally charged and impossible to adhere to. But there are a lot of people who choose this life style - some even without any moral pressure. Other people choose monogamy (most of them nowadays in its weaker, <em>serial</em> variation) and live a happy life with it.</p>
<p>(Concerning the terminology here: I can't quite put my finger on it but I have the feeling that both authors mean <em>Unit Testing</em> when they speak of <em>Test Driven Development</em>. Just to be clear about my point, I'm gonna use the term <em>Unit Testing</em> from now on.)</p>
<p>The important thing for me is to <em>have a choice</em>. And also to consider them. And to keep in mind that there may be incompatibilities between the styles. If a monogamist starts a relationship with an abstainer, both of them will become unhappy. If somebody does not want to use a test-first development style in his project, that's fine with me. But I won't collaborate with him.</p>
<p>And of course there are even more alternatives. Polyamory for example. And I might be stretching the metaphor a bit here but to me, the polyamorous approach to testing would be to do Unit Testing as well as testing through the GUI as well as all the testing strategies that lie between those two extremes.</p>
<p><img alt="spectrum of testing strategies" src="/res/testing/spectrum.png"></p>
<p>I often wonder why so little is said about the range in the middle and why both, David and Robert seem to ignore it.</p>
<h2>Trust</h2>
<p>In the end it's all about one thing: <strong>Trust</strong>.</p>
<p>That's a very powerfull thing. So powerful, people tend to become quite passionate once they start working on a non-trivial code base that they could trust completely. I at least became very passionate about it.</p>
<p>So the most important question is: how do we achieve this level of trust? How can we be certain that a programm <em>works as expected</em> to the point that we can deploy purely on the basis of automated tests?</p>
<p>For TDDlers it's almost trivial to answer the question if a programm <em>works as expected</em>. They write their expectations in code. So it works if all tests pass. Problem solved. But for non-programmers it's not that easy. Their expectations are intransparently translated into something they cannot understand. They only have the GUI.</p>
<p>But as Uncle Bob states correctly, testing through the GUI is slow. Very slow if done manually, and still pretty slow but also very fragile if done automatically. It's fragile because the GUI changes way more than the <em>behaviour</em> of the software so GUI tests tend to give a lot of false positives and thus are maintanance heavy. The following graph shows my impression of how execution time increases with the level of integration.</p>
<p><img alt="execution time over integration" src="/res/testing/execution_time.png"></p>
<p>But tests written at GUI level are very attractive for business stake holders because they can understand them and therefore <em>trust</em> them. But we can't test the entire system through the GUI so we need Unit level tests as well. Tests that the developers can trust.</p>
<p>In my opinion, both testing approaches are complementary and trust from all sides can only be achieved if they are both implemented. But in the right mix that keeps the balance.</p>
<h2>Daedalus Testing</h2>
<p>But what about that range of testing approaches between the two extremes? Unfortunately the terminology is highly inconsistent here but I'll try to put them in order, starting at the most integrational strategy becoming more granular. Here is what this scale could look like:</p>
<ul>
<li>(G)UI</li>
<li>End-to-end</li>
<li>System</li>
<li>Integration</li>
<li>Module</li>
<li>Component</li>
<li>Unit</li>
</ul>
<p>Since developers can't trust GUI testing and business people can't trust anything too close to Unit testing the ideal approach could be to stay in a range somewhere not high and not too low. Let's call this approach <em>Daedalus Testing</em>.</p>
<p>The maximum granularity of this range is where business people stop understanding the domain and the maximum of integration is where fragility and execution time become too high for practical use.</p>
<p>These tests need to be written in a language that developers as well as non-developers understand. I will write about how this can be done in my next article.</p>
<h2>Test First</h2>
<p>There are two discussions which are often times interwinded. One is about automated testing vs. manual testing. The other one is about <em>Test First</em> vs. <em>Test Later</em>. Since this is rarely addressed explicitly, I'm not sure what the opposition to automated testing looks like or if it even exists.</p>
<p>But for me personally, the <em>only</em> reliable way of producing a complete suite of high quality automated tests consistently is to write them first. I also agree completely with Uncle Bob when he says that <a href="http://blog.8thlight.com/uncle-bob/2013/09/23/Test-first.html">"Tests are first in all things"</a>. And I consider it proven that writing them first has a lot of positive effects on the production code but these effects are secondary to me. The most important thing by a long shot is trust.</p>
<p>If you want to find out if a test suite is complete just try to delete code that doesn't make any test fail.</p>
<h2>Up Next</h2>
<p>As said in the beginning, I originally wanted to write about my testing approach, the tool I wrote for it and how I plan to use it as a managment strategy in my current project. And I will. But I also wanted to cover the philosophical ground which I hope to have done here.</p>Codemotion 2014 Rome2014-04-17T00:00:00+02:002014-04-17T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2014-04-17:/codemotion-2014-rome.html<p>Last week I had the pleasure of presenting my talk on <a href="http://specificationbyexample.com">Specification by Example</a> (aka Behaviour-Driven Development) at the <a href="http://rome.codemotionworld.com/2014/">Codemotion</a> conference in Rome in front of a very attentive and responsive audience.</p>
<p><a href="/res/codemoton_roma_2014_Nikolas_Martens.pdf">You can find the slides here</a> and some pics <a href="https://twitter.com/THEBUCKET3/status/455019595779547136">here</a> and <a href="https://twitter.com/cyberneticlove/status/455011378517278720">here</a>. Thanks for those!</p>
<p>The talks I …</p><p>Last week I had the pleasure of presenting my talk on <a href="http://specificationbyexample.com">Specification by Example</a> (aka Behaviour-Driven Development) at the <a href="http://rome.codemotionworld.com/2014/">Codemotion</a> conference in Rome in front of a very attentive and responsive audience.</p>
<p><a href="/res/codemoton_roma_2014_Nikolas_Martens.pdf">You can find the slides here</a> and some pics <a href="https://twitter.com/THEBUCKET3/status/455019595779547136">here</a> and <a href="https://twitter.com/cyberneticlove/status/455011378517278720">here</a>. Thanks for those!</p>
<p>The talks I enjoyed the most were by <a href="https://twitter.com/brucel">Bruce Lawson</a> and <a href="https://twitter.com/gar1t">Garrett Smith</a>. Bruce managed to make listening to his presentation as enjoyable as reading <a href="http://en.wikipedia.org/wiki/The_Hitchhikers_Guide_to_the_Galaxy">The Hitchhiker's Guid the Galaxy</a>, which is very much enjoyable. So if you ever want to know what's the best way to <a href="https://twitter.com/rtens_/status/454625284591853569">Destroy the Web</a>, talk to this guy.</p>
<p>Garret Smith, whom I used to know only by his blogs and tweets, gave the most inspiring talk I have seen in a while about how software has a more in common with an organism than a structure and that in order to write good software, first we need to accept that we're not gods and can't plan everything. It's the same school of thoughts as Hintjens' <a href="http://hintjens.com/blog:74">Living Systems</a> and <a href="http://theleanstartup.com/">The Lean Startup</a>. Both which I became a big fan of recently.</p>
<p>Since Rome in springtime is said to be especially beautifull I arrived a day earlier which I spent walking around the litterally the whole city, enjoying the sun and eating plenty of gelato. Of course I visited the <a href="/res/rome2014/vittorio.jpg">Vittorio II Monument</a>, walked along the Foro Romano to he Coloseum and took a nap in the Circo Maximo. Then I strolled to the <a href="/res/rome2014/tiber_isle.jpg">Tiber island</a> and through the inner city to the Vatican where they already prepared for the <a href="/res/rome2014/st_pauls.jpg">Easter Mass</a>. I also visited the park of Villa Borghese which I requires a little climb but the view from <a href="/res/rome2014/pincio.jpg">Pincio</a> is definitely worth it. But the best part of the whole trip was definitely the food. Simply incredible.</p>
<p><a href="/res/rome2014/vittorio.jpg" target="_blank"><img src="/res/rome2014/vittorio.jpg" style="height: 180px"/></a>
<a href="/res/rome2014/tiber_isle.jpg" target="_blank"><img src="/res/rome2014/tiber_isle.jpg" style="height: 180px"/></a>
<a href="/res/rome2014/st_pauls.jpg" target="_blank"><img src="/res/rome2014/st_pauls.jpg" style="height: 180px"/></a>
<a href="/res/rome2014/pincio.jpg" target="_blank"><img src="/res/rome2014/pincio.jpg" style="height: 180px"/></a></p>The Assembler Excursion2014-03-08T00:00:00+01:002014-03-08T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2014-03-08:/the-assembler-excursion.html<p>Last week we went oldschool at our monthly <a href="http://codingdojo.org/">Coding Dojo</a> and programmed in Assembler for the 6502 microprocessor thanks to an awesome <a href="http://skilldrick.github.io/easy6502/">tutorial</a> by <a href="https://twitter.com/skilldrick">Nick Morgan</a> that made me wanna try it out myself. Turned out it's a lot harder than we thought and we achieved little more during the …</p><p>Last week we went oldschool at our monthly <a href="http://codingdojo.org/">Coding Dojo</a> and programmed in Assembler for the 6502 microprocessor thanks to an awesome <a href="http://skilldrick.github.io/easy6502/">tutorial</a> by <a href="https://twitter.com/skilldrick">Nick Morgan</a> that made me wanna try it out myself. Turned out it's a lot harder than we thought and we achieved little more during the whole session than painting the background blue. But it got me curious and I ended up knee-deep in Assembler.</p>
<h2>The Coding Dojo</h2>
<p>Last August, a <a href="http://martin.holzhauer.eu/">colleague</a> of mine told me about this thing called <a href="http://codingdojo.org/">Coding Dojo</a> and I since we couldn't find any active ones in Berlin, we started to organize our own at the <a href="http://researchgate.net">ResearchGate</a> offices. The idea is to get together with other coders (aka hackers/developers/programmers) and work on a programming challenge together in order to practice and learn from eachother. We usually pair up but other forms are possible. It's always great fun so if you are curious drop by. You can find the all the infos on <a href="http://github.com/researchate/CodingDojo">github</a>.</p>
<p>By the way: in the meatime I found two other Coding Dojos or dojo-like meetups: <a href="http://www.meetup.com/Agile-Developers-Berlin/">agile developers</a> and <a href="http://www.softwerkskammer.org/">softwarekammer</a></p>
<p>There is a bunch of small, well-defined challenges called <a href="http://codingdojo.org/cgi-bin/index.pl?KataCatalogue">Katas</a> which are a good starting point. A Kata is an excersice which is meant to be repeated over and over. In the martial arts, it's a movement that you repeat until it becomes second nature so you don't have to think about it during battle and concentrate on more important things like staying alive. Just like you don't have to think about all the tiny movements involved in changing gears as an experienced driver.</p>
<p>So sometimes we do a Kata at the Dojo but sometimes we do other tings like a simple Regular Expression matcher or drawing patterns on a Christmas tree via HTTP. And since this really nice <a href="http://skilldrick.github.io/easy6502/">tutorial</a> inspired me to try it out myself, last week we did some Assembler for the <a href="http://en.wikipedia.org/wiki/MOS_Technology_6502">6502</a> micropocessor.</p>
<h2>The Machine Code</h2>
<p>What I like most about prgramming is how it turns my thoughts into reality. I imagine that this must be even more thrilling for architects that can wallk and touch their brain childs but being able to push all these pixels around at will is already pretty cool for me. Magical even. But with all the layers of abstraction, the connection between the keys I press and the pixels that light up is all but transparent.</p>
<p>So ever since I started programming I was fascinated with Machine Code. It's where the magic happens, where words become reality. It's that line between ideas and physics. Every line of code I write, no matter in which language is eventually distilled into a bunch of machine instructions before it becomes electrical signals that contol millions of tiny lamps just to trick my brain into thinking I'm looking at a small kitten rolling on a floor. If you are not blown out of your mind by that you haven't really thought about it yet.</p>
<p>So how does machine code look like? Well for example like this:</p>
<div class="highlight"><pre><span></span><span class="err">1010 0101 0000 0001 </span>
<span class="err">0110 1001 0000 0010 </span>
<span class="err">1000 0101 0000 0011</span>
</pre></div>
<p>These numbers can be translated into a slightly more human-readable form called Assembler:</p>
<div class="highlight"><pre><span></span><span class="n">LDA</span> <span class="nv">$01</span>
<span class="n">ADC</span> <span class="c1">#$02</span>
<span class="n">STA</span> <span class="nv">$03</span>
</pre></div>
<p>And if you wanted to translate these lines into english you might get something like</p>
<div class="highlight"><pre><span></span><span class="err">Look up the number in the memory cell number one and remember it</span>
<span class="err">Add the number two to that number and remember the result</span>
<span class="err">Put the resulting number into the memory cell number three</span>
</pre></div>
<h2>The Micro Processor</h2>
<p>The <em>machine</em> in Machine Code is the processor. When I say "Add the number to that number you remembered and remember the result", the processor is the one that actually does that. Describing how exactly that works would definitely blow up this article but let's just say that these zeros and ones above correspond to off and on positions of many many switches. And like in a big building, if you set the right light switches at the right time to the right positions, you can suddenly do things like play pong.</p>
<p>I have this idea of building a <em>Water Computer</em> that uses water instead of electrons. It would be huge and slow and possibly quite wet but it would be perfect to demonstrate how a processor works because everythings would be so slow that you could actually watch it happening. Of course any liquid would do so in the future I might call it <em>Beer Computer</em> for marketing reasons.</p>
<p>Anyway, like my hypothetical water processor, these processors used to be huge and expensive but eventually became tiny (hence micro) and cheap enough so everybody could have one. Born was the personal computer. Nowadays we are surrounded by micro processors. They are in out computers (duh), cars, blenders, dish washers, everywhere. They are usually black and square and flat and get really hot if you watch a lot of cat videos.</p>
<h2>The Emulator</h2>
<p>The great thing about software is that you can build anything with it. Even a computer. A computer built from software instead of silicon, gold, aluminum and stuff is called an <em>emulator</em>. So you can write a programm that behaves just like a certain processor. Such an emulator has the big advantage that you can very easily look inside it. This is very hard with a physical micro processor since it's so tiny and everything happens so fast.</p>
<p>For the Coding Dojo, we mostly used the emulator on <a href="http://www.6502asm.com/">6502asm.com</a> which works well but has limited debugging abilities and is also rather slow. So I went looking for an emulator that is not written in JavaScript but allows the same configuration as the one in the tutorial - with display, random number generator and key input </p>
<p>Since I couldn't find one within ten minutes, I did what every sane software developer would do - I wrote my one. You can find the result <a href="https://github.com/rtens/6502">here</a>. And although the value for humanity of this exercise is questionable, I once again felt why I'm such a big fan of reinventing the wheel. By re-building the whole processor I got to know it a lot better than by using it and it was a lot more fun than reading a 500-pages technical book. And probably took the same time (I'm a slow reader).</p>
<h2>The Sphere</h2>
<p>When we sat down to write some Assembler at the Coding Dojo and started wondering, what our pogramm should actually do, Rob had the idea to build a ray tracer for a sphere. In other words, to paint a circle. I loved it because it gave me a good excuse to do some actual math and it sounds cool. I was suprised by how much math I've forgotten in a couple of years. But an hour later we had roughly implemented the ray tracing algorithm. In C.</p>
<p>Translating the C program into Assembler is trivial of course. Or so we thought. We thought wrong. In the remaining hour we achieved little more than paining the background. In blue. But we sure had a good time doing so.</p>Small Steps (sudoku edition)2014-02-06T00:00:00+01:002014-02-06T00:00:00+01:00Nikolas Martenstag:blog.rtens.org,2014-02-06:/small-steps-sudoku-edition.html<p>After <a href="small-steps-at-bephpug.html">trying out live coding</a> at the October meeting of the <a href="http://bephpug.de">Berlin PHP user group</a> last year, I tasted blood. So I decided to repeat it with a more complex problem.</p>
<p>At that point I remembered some articles discussing the <a href="http://johannesbrodwall.com/2010/04/06/why-tdd-makes-a-lot-of-sense-for-sudoko/">pros</a> and <a href="http://devgrind.com/2007/04/25/how-to-not-solve-a-sudoku/">cons</a> of TDD in the context of a …</p><p>After <a href="small-steps-at-bephpug.html">trying out live coding</a> at the October meeting of the <a href="http://bephpug.de">Berlin PHP user group</a> last year, I tasted blood. So I decided to repeat it with a more complex problem.</p>
<p>At that point I remembered some articles discussing the <a href="http://johannesbrodwall.com/2010/04/06/why-tdd-makes-a-lot-of-sense-for-sudoko/">pros</a> and <a href="http://devgrind.com/2007/04/25/how-to-not-solve-a-sudoku/">cons</a> of TDD in the context of a <a href="http://en.wikipedia.org/wiki/Sudoku">sudoku</a> solver. Seems like there is still <a href="https://www.google.de/search?q=sudoku+tdd">more to find</a> on this discussion. And I decided to join it.</p>
<p>So I broke down the sudoku solver problem into "small steps" - the smallest I could find - and presented to whole process, from an empty file to a working (yet somewhat slow) solver at this week's user group meeting. <a href="/res/sudoku_solver.zip">You can find the result here</a>. Since a soduko solver is all but trivial, I wasn't sure if I could do it live without creating a horrible mess. But with the help of a very attentive user group it worked out just fine and it was great fun for me. And I'm glad to <a href="https://twitter.com/IchHabRecht/status/430808466295648256">hear</a> that I wasn't the only one enjoying it.</p>Codemotion 2013 Madrid2013-10-26T00:00:00+02:002013-10-26T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2013-10-26:/codemotion-2013-madrid.html<p>On the last weekend I had the opportunity to present my talk about <a href="http://specificationbyexample.com">Specification by Example</a> (aka Behaviour-Driven Development) at the <a href="http://madrid.codemotionworld.com/">Codemotion</a> conference in Madrid.</p>
<p><a href="/res/sbe_froscon8.pdf">You can find the commented slides here</a> and thanks for <a href="https://twitter.com/wnohang/status/391592132667928577">the</a> <a href="https://twitter.com/aamormo/status/391516235118436353">awesome</a> <a href="https://twitter.com/daviddiazgismer/status/391524498979434496">feeback</a>!</p>
<p>Unfortunately I could only stay one night because of other commitments so …</p><p>On the last weekend I had the opportunity to present my talk about <a href="http://specificationbyexample.com">Specification by Example</a> (aka Behaviour-Driven Development) at the <a href="http://madrid.codemotionworld.com/">Codemotion</a> conference in Madrid.</p>
<p><a href="/res/sbe_froscon8.pdf">You can find the commented slides here</a> and thanks for <a href="https://twitter.com/wnohang/status/391592132667928577">the</a> <a href="https://twitter.com/aamormo/status/391516235118436353">awesome</a> <a href="https://twitter.com/daviddiazgismer/status/391524498979434496">feeback</a>!</p>
<p>Unfortunately I could only stay one night because of other commitments so I took the 6:40am flight on Friday and arrived home 29 hours later. A very intense trip. But one very much worth while.</p>
<p>I don't know the official numbers but I was told that there were around 1200 attendees which resulted in me not being able to attend a session I was interested in because of a crowded room. And when I say crowded I mean Tokyo subway-style crowded. In the end, my short stay, the need to prepare my own talk, crowded rooms and last but not least the warm spanish sun all led to me only seeing one session of the whole conference.</p>
<p>Instead I spent a lot of time in the grass and meeting fellow speakers including <a href="https://twitter.com/dbu">David Buchmann</a> from Switzerland and <a href="https://twitter.com/CodeStars">Ole Michaelis</a> from Hamburg who had visited the <a href="http://bephpug.de">Berlin PHP usergroup</a> a couple of weeks earlier. Ole was kind enough to help me with my proposals since I'm having a hard time getting accepted at conferences.</p>
<p>At my own session on Saturday afternoon was every seat taken as well and therefore I was probably facing my biggest audience yet with around 150 people which might be a reason why I enjoyed this talk a bit more than usually. But also everybody was increadibly attentive and responsive so I can definitely say that I had an excellent time at the Codemotion 2013 in Madrid.</p>Small steps at bephpug2013-10-07T00:00:00+02:002013-10-07T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2013-10-07:/small-steps-at-bephpug.html<p>At the <a href="http://bephpug.de">Berlin PHP user group</a> last week I had two "firsts". It was my first time live-coding and I thought while I'm at it I could also do a "live" presentation on my hybrid <a href="http://www.samsung.com/us/computer/pcs/XE500T1C-A05US">tablet/netbook</a>. Both went surprisingly well. And thanks guys <a href="https://twitter.com/__edorian/status/385123964148019200">for</a> <a href="https://twitter.com/klimpong/status/385109934956093440">all</a> <a href="https://twitter.com/bephpug/status/385107357145239552">your</a> <a href="https://twitter.com/localheinz/status/385276391639773184">feedback</a>.</p>
<p>The talk …</p><p>At the <a href="http://bephpug.de">Berlin PHP user group</a> last week I had two "firsts". It was my first time live-coding and I thought while I'm at it I could also do a "live" presentation on my hybrid <a href="http://www.samsung.com/us/computer/pcs/XE500T1C-A05US">tablet/netbook</a>. Both went surprisingly well. And thanks guys <a href="https://twitter.com/__edorian/status/385123964148019200">for</a> <a href="https://twitter.com/klimpong/status/385109934956093440">all</a> <a href="https://twitter.com/bephpug/status/385107357145239552">your</a> <a href="https://twitter.com/localheinz/status/385276391639773184">feedback</a>.</p>
<p>The talk has the name "Small Steps - the magic of TDD" and is basically about how test-driven development enables you to develop a programm taking one tiny step at a time. I put the "slides" and code <a href="/res/Nikolas_Martens_Small_steps__bephpug.zip">here</a>. Let me know what you think.</p>Froscon 20132013-08-29T00:00:00+02:002013-08-29T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2013-08-29:/froscon-2013.html<p>Last weekend I had the pleasure of talking about Specification by Example at the <a href="http://www.froscon.de/">Free and Open Source Software Conference</a> near Bonn. <a href="/res/sbe_froscon8.pdf">You can find the commented slides about Specification by Example here</a>. If you watched the talk, I would appreciate your feedback <a href="http://programm.froscon.org/2013/events/1249.html">here</a>.</p>
<p>I used the opportunity to finally …</p><p>Last weekend I had the pleasure of talking about Specification by Example at the <a href="http://www.froscon.de/">Free and Open Source Software Conference</a> near Bonn. <a href="/res/sbe_froscon8.pdf">You can find the commented slides about Specification by Example here</a>. If you watched the talk, I would appreciate your feedback <a href="http://programm.froscon.org/2013/events/1249.html">here</a>.</p>
<p>I used the opportunity to finally get in touch with LISP and its relatives and got quite intrigued by Moritz Heidkamp <a href="http://programm.froscon.org/2013/events/1280.html">view on the world</a> promoting s-expressions to be used as syntax for everything including HTML, CSS and SQL. I instantly became a fan of the regular syntax.</p>
<p>But I was brought down to the cruel reality again when I was trying to actually build something at the <a href="http://programm.froscon.org/2013/events/1251.html">Clojure workshop</a>. The goal was to implement the <a href="http://en.wikipedia.org/wiki/Conway's_Game_of_Life">Game of Life</a> and I failed miserably in wrapping my head around the everything-as-a-function way of thinking. Also, I spent most of the time getting the test runner to work in order to do proper TDD which seems to be a veeery unusual approach in the Lisp/Clojure world. But in the end I could run a test suite without restarting the JVM (which took almost a minute on my Atom) so I count that as a success.</p>
<p>My first session of the PHP subconference was a talk about our awesome architecture at ResearchGate, <a href="http://programm.froscon.org/2013/events/1244.html">marrying frontend and backend</a> given by my colleagues <a href="https://twitter.com/BastianHofmann">Bastian</a> and <a href="https://twitter.com/__edorian">Volker</a>. I owe quite a bit to Volker for it was him who suggested to me to talk at conferences after I talked at the PHP user group a couple of times.</p>
<p>Saturday's last session for me was <a href="http://www.liane-thoennes.de/">Liane Thönnes</a> and Tim Schneider talking about cats and dogs aka <a href="http://programm.froscon.org/2013/events/1268.html">Designers and Developers</a>, their differences, their misunderstandings and their similarities. The talk was very entertaining and inspiring and strengthened my opinion that a lot of wasted time can be avoided by integrating designer into the development team.</p>
<p>The rest of the evening I took the opportunity to get to know the attending part of the PHP community which resulted in a great night with very enjoyable and interesting conversations with a lot of Kölsch. Since the BBQ took a while to arrive and then had a queue of at least 100m I declared Kölsch and Pfeffi as my dinner. I was even taught the "Hallemann" (Hollamann?) as tricky way to enjoy both at the same time. In short, I had an exquisit time and was very happy to have the last slot on Sunday.</p>TDD Case Study2013-07-06T00:00:00+02:002013-07-06T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2013-07-06:/tdd-case-study.html<p>I'm a big fan of <a href="http://c2.com/cgi/wiki?TestDrivenDevelopment">Test-Driven Development</a> and have been using it in almost all <a href="https://github.com/rtens">projects</a> for a while now with astonishing results. If you are not convinced by TDD, drop me a <a href="https://twitter.com/rtens_">line</a> and I will do my best to change that. Although at first seemingly counter-intuitive, TDD quickly …</p><p>I'm a big fan of <a href="http://c2.com/cgi/wiki?TestDrivenDevelopment">Test-Driven Development</a> and have been using it in almost all <a href="https://github.com/rtens">projects</a> for a while now with astonishing results. If you are not convinced by TDD, drop me a <a href="https://twitter.com/rtens_">line</a> and I will do my best to change that. Although at first seemingly counter-intuitive, TDD quickly became as natural as me as camel-casing. But while showing it to fellow developers, I noticed how many only understand what test-driven means after having seen it in action. In this article I show how I implemented the solution for two exemplary problems with TDD step-by-step.</p>
<h2>Programming Exercises</h2>
<p>I Recently was asked for some programming exercises that could be used to improve one's software development skills. I came up with the following list of exercises with rapidly increasing difficulty.</p>
<ol>
<li>Calculate the number at a given position of the Fibonacci series</li>
<li>Sort a list using Bubble sort</li>
<li>Test if a string matches a Regular Expression with a defined set of constructs (e.g. <code>^</code> <code>$</code> <code>.</code> <code>*</code> and literal matching)</li>
<li>Solver for the goat-wolf-cabbage puzzle</li>
<li>An "optimal move" suggester for any state of a tic-tac-toe game</li>
</ol>
<p>Of course the exercises should be implemented test-driven. A key concept of TDD is to develop a solution iteratively in small steps. The smaller the better. The hard part is often times to be able to identify these small steps. For the Fibonacci series the steps are the positions themselves, for Bubble sort you can use lists with increasing complexity (starting with two elements in order, out of order, then three etc.) and the complexity of Regular Expressions can be fine-tuned easily as well by limiting the number of constructs. But with exercise number four I got stuck and did not instantly find a test-driven approach which is why I dedicated most of this article to it. But let's look at the easy example first.</p>
<h2>Test-Driven Fibonacci</h2>
<p>As said, the tests for the Fibonacci series can be easily deduced from its first couple of values.</p>
<div class="highlight"><pre><span></span><span class="err">f(0) = 0</span>
<span class="err">f(1) = 1</span>
<span class="err">f(2) = 1</span>
<span class="err">f(3) = 2</span>
<span class="err">f(4) = 3</span>
<span class="err">f(5) = 5</span>
</pre></div>
<p>The implementation of these tests could look like the following snippet. I use <a href="http://www.python.org/">Python</a> in version 2.7 without a test framework in this article. Feel free to use the language and test framework of your choice, for example <a href="http://www.vogella.com/articles/JUnit/article.html">JUnit</a>.</p>
<div class="highlight"><pre><span></span><span class="k">assert</span> <span class="n">fibonacci</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">fibonacci</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
<span class="k">assert</span> <span class="n">fibonacci</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
<span class="k">assert</span> <span class="n">fibonacci</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span>
<span class="k">assert</span> <span class="n">fibonacci</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span>
<span class="k">assert</span> <span class="n">fibonacci</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="mi">5</span>
</pre></div>
<p>Now when I run this, all tests will fail. There is no function called <code>fibonacci</code> yet. But it's good to know that my test runner works as expected. So let's implement the first test.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">return</span> <span class="mi">0</span>
</pre></div>
<p>Run the tests again. Success! The first test passes. And although all the other ones are still failing I am content with myself for having found the tiniest step imaginable. Let's continue with the second test.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">0</span>
<span class="k">elif</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
</pre></div>
<p>Yay! Two tests pass. Does this look like cheating to you? It's not. I am just following the specification. If it would only consist of the first two lines I would be done. But unfortunately I am not. So let's do another one.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">0</span>
<span class="k">elif</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">elif</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
</pre></div>
<p>Running the tests confirms that I am 60% done. Time for a coffee break so I can tackle the hard part with new energy. Of course I could implement all five tests with if-else statements. But besides writing the test and making it pass, there is a third step in the TDD circle: refactoring. So the whole cycle goes</p>
<div class="highlight"><pre><span></span><span class="err">1. Write the test.</span>
<span class="err">2. Make it pass.</span>
<span class="err">3. Refactor.</span>
</pre></div>
<p>So apparently I have ignored the last step until now. Let's fix that and remove duplication from the production code.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">n</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
<p>Ok. This was a little more than obvious refactoring. But TDD doesn't save you from actually using your brain. And we need to get to the more interesting example.</p>
<h2>Save the goat</h2>
<p>As metnioned before, when I came to exercise four, I got stuck. I could not see any "small" steps that would lead me to something like this.</p>
<div class="highlight"><pre><span></span><span class="nb">print</span> <span class="n">solvePuzzle</span><span class="p">()</span> <span class="c1"># => g_wgc_g which means "move goat", "move back empty", "move wolf", "move back goat" ...</span>
</pre></div>
<p>It seems like either it solves the puzzle or it doesn't. There is nothing in between. So I went ahead and implemented the solver in one giant leap instead of many small steps.</p>
<div class="highlight"><pre><span></span><span class="k">assert</span> <span class="n">solvePuzzle</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'g_wgc_g'</span>
</pre></div>
<p>This was very unpleasant. I didn't see a single passing test until the end and even worse, I never had an excuse for a coffee break. But as usually, sometimes you need to disengage from a problem in order to solve so I went to bed, took a shower, had breakfast and came up with this.</p>
<div class="highlight"><pre><span></span><span class="n">puzzle</span> <span class="o">=</span> <span class="n">Puzzle</span><span class="p">()</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'g'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'w'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'c'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addConstraint</span><span class="p">(</span><span class="s1">'g'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addConstraint</span><span class="p">(</span><span class="s1">'g'</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'g_wgc_g'</span>
</pre></div>
<p>The design is dramatically different from the previous implementation. The new solver does not any more just use a puzzle with a goat, a wolf and a cabbage but any puzzle. I can configure the puzzle by adding animals and other objects and putting constraints on which objects should not be left alone. This means I can make up harder puzzles, puzzles without solution but most importantly, also easier ones. Suddenly, there is a small step.</p>
<div class="highlight"><pre><span></span><span class="n">puzzle</span> <span class="o">=</span> <span class="n">Puzzle</span><span class="p">()</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'a'</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'a'</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>This time I will specify the tests iteratively after I made the last one pass. TDD works either way. You can either specify the entire behaviour up-front with increasing complexities or discover the steps along the way. Usually it's a mix of both. I also put a red or green bar below every code snippet to indicate the state of the test suite. So let's make the first test pass. We need a class and two functions.</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Puzzle</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">addObject</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">id</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="k">return</span> <span class="n">move</span><span class="p">(</span><span class="s1">'a'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">move</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">object</span>
</pre></div>
<div style="background-color: green"> </div>
<p>That's what I call a tiny step. I didn't really implement anything and the test is already passing. Let's refactor that duplication in <code>solve</code>.</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Puzzle</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">objects</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">addObject</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">id</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="k">return</span> <span class="n">move</span><span class="p">(</span><span class="n">puzzle</span><span class="o">.</span><span class="n">objects</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</pre></div>
<div style="background-color: green"> </div>
<p>This already solves all puzzles with just one object. How about two objects?</p>
<div class="highlight"><pre><span></span><span class="n">puzzle</span> <span class="o">=</span> <span class="n">Puzzle</span><span class="p">()</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'x'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'y'</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'x_y'</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>Fail! But that was expected. Actually, when doing TDD, I always make sure to have seen every test failing at least once. It's the best way to confirm the tests are actually doing something. The reason for the failing test is that <code>solve</code> still only moves the first object. So let's try to fix this.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="n">moves</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">for</span> <span class="nb">object</span> <span class="ow">in</span> <span class="n">puzzle</span><span class="o">.</span><span class="n">objects</span><span class="p">:</span>
<span class="n">moves</span> <span class="o">+=</span> <span class="n">move</span><span class="p">(</span><span class="nb">object</span><span class="p">)</span>
<span class="k">return</span> <span class="n">moves</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>Seems like I am getting closer. Now I get 'xy' as the solution. And if the goat, the wolf and the cabbage were standing on catapults this would actually work but for our puzzle the farmer can only move an object if they are on the same side. This means we need to know on which side everyone (the objects and the farmer) is. Let's put this information into the dictionary <code>positions</code> which is indexed by the object (including the farmer) and has a boolean value indicating if the object is on the left side of the river (<code>True</code>) or on the right side (<code>False</code>). </p>
<div class="highlight"><pre><span></span><span class="n">farmer</span> <span class="o">=</span> <span class="s1">'!'</span>
<span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="n">positions</span> <span class="o">=</span> <span class="n">getStartPositions</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span>
<span class="n">moves</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">for</span> <span class="nb">object</span> <span class="ow">in</span> <span class="n">puzzle</span><span class="o">.</span><span class="n">objects</span><span class="p">:</span>
<span class="n">moves</span> <span class="o">+=</span> <span class="n">move</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">positions</span><span class="p">)</span>
<span class="k">return</span> <span class="n">moves</span>
<span class="k">def</span> <span class="nf">getStartPositions</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="n">start</span> <span class="o">=</span> <span class="p">{</span><span class="n">farmer</span><span class="p">:</span> <span class="kc">True</span><span class="p">}</span>
<span class="k">for</span> <span class="nb">object</span> <span class="ow">in</span> <span class="n">puzzle</span><span class="o">.</span><span class="n">objects</span><span class="p">:</span>
<span class="n">start</span><span class="p">[</span><span class="nb">object</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">return</span> <span class="n">start</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>I guess a coder in the true python spirit would write the second function as</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">getStartPositions</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">dict</span><span class="p">([(</span><span class="nb">object</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span> <span class="k">for</span> <span class="nb">object</span> <span class="ow">in</span> <span class="p">[</span><span class="n">farmer</span><span class="p">]</span> <span class="o">+</span> <span class="n">puzzle</span><span class="o">.</span><span class="n">objects</span><span class="p">])</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>Also, an object can only be moved when it's on the same side as the farmer.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">move</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">positions</span><span class="p">):</span>
<span class="k">if</span> <span class="n">positions</span><span class="p">[</span><span class="nb">object</span><span class="p">]</span> <span class="o">==</span> <span class="n">positions</span><span class="p">[</span><span class="n">farmer</span><span class="p">]:</span>
<span class="n">positions</span><span class="p">[</span><span class="nb">object</span><span class="p">]</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">positions</span><span class="p">[</span><span class="nb">object</span><span class="p">]</span>
<span class="n">positions</span><span class="p">[</span><span class="n">farmer</span><span class="p">]</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">positions</span><span class="p">[</span><span class="n">farmer</span><span class="p">]</span>
<span class="k">return</span> <span class="nb">object</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="s1">''</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>Let's run it... Seems like the farmer gets stuck on the right side. Let's give him the chance to go back without cargo.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">move</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">positions</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">object</span> <span class="o">==</span> <span class="s1">'_'</span><span class="p">:</span>
<span class="n">positions</span><span class="p">[</span><span class="n">farmer</span><span class="p">]</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">positions</span><span class="p">[</span><span class="n">farmer</span><span class="p">]</span>
<span class="k">return</span> <span class="s1">'_'</span>
<span class="p">[</span><span class="o">...</span><span class="p">]</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>This means that we have to add <code>'_'</code> (nothing) to the list of objects that can be moved.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="n">positions</span> <span class="o">=</span> <span class="n">getStartPositions</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span>
<span class="n">moves</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">for</span> <span class="nb">object</span> <span class="ow">in</span> <span class="n">getMovables</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="n">moves</span> <span class="o">+=</span> <span class="n">move</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">positions</span><span class="p">)</span>
<span class="k">return</span> <span class="n">moves</span>
<span class="k">def</span> <span class="nf">getMovables</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="k">return</span> <span class="n">puzzle</span><span class="o">.</span><span class="n">objects</span> <span class="o">+</span> <span class="p">[</span><span class="s1">'_'</span><span class="p">]</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>Let's run it. Bummer. Now the first test fails. Seems like it doesn't know when to stop. And while we're at it, let's have the farmer make trips repeatedly until everybody is on the other side.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="n">positions</span> <span class="o">=</span> <span class="n">getStartPositions</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span>
<span class="n">moves</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">while</span> <span class="p">(</span><span class="kc">True</span><span class="p">):</span>
<span class="k">for</span> <span class="nb">object</span> <span class="ow">in</span> <span class="n">getMovables</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="n">moves</span> <span class="o">+=</span> <span class="n">move</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">positions</span><span class="p">)</span>
<span class="k">if</span> <span class="n">positions</span> <span class="o">==</span> <span class="n">getTargetPositions</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="k">return</span> <span class="n">moves</span>
<span class="k">def</span> <span class="nf">getTargetPositions</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">dict</span><span class="p">([(</span><span class="nb">object</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span> <span class="k">for</span> <span class="nb">object</span> <span class="ow">in</span> <span class="p">[</span><span class="n">farmer</span><span class="p">]</span> <span class="o">+</span> <span class="n">puzzle</span><span class="o">.</span><span class="n">objects</span><span class="p">])</span>
</pre></div>
<div style="background-color: green"> </div>
<p>Bingo! Both tests are passing. Next step: three objects.</p>
<div class="highlight"><pre><span></span><span class="n">puzzle</span> <span class="o">=</span> <span class="n">Puzzle</span><span class="p">()</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'c'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'w'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'g'</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'c_w_g'</span>
</pre></div>
<div style="background-color: green"> </div>
<p>Something that works with two usually works with three as well (which is why software engineers count "zero, one, many") so I can already modify this test to make sure that the goat and the wolf are not left alone.</p>
<div class="highlight"><pre><span></span><span class="n">puzzle</span><span class="o">.</span><span class="n">addConstraint</span><span class="p">(</span><span class="s1">'g'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'w_c_g'</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>We can do this by checking for each move if the new constellation is "valid", meaning that no two objects that are unhealthy for each other are left alone on one side. So I change the inner loop of the <code>solve</code> function to</p>
<div class="highlight"><pre><span></span><span class="k">for</span> <span class="nb">object</span> <span class="ow">in</span> <span class="n">getMovables</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="n">nextMove</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">positions</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">isValid</span><span class="p">(</span><span class="n">puzzle</span><span class="p">,</span> <span class="n">positions</span><span class="p">)):</span>
<span class="n">moves</span> <span class="o">+=</span> <span class="n">nextMove</span>
<span class="k">if</span> <span class="n">positions</span> <span class="o">==</span> <span class="n">getTargetPositions</span><span class="p">(</span><span class="n">puzzle</span><span class="p">):</span>
<span class="k">return</span> <span class="n">moves</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>If I run this now python reminds me that I need to define the <code>isValid</code> function. So I do her this favour.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">isValid</span><span class="p">(</span><span class="n">puzzle</span><span class="p">,</span> <span class="n">positions</span><span class="p">):</span>
<span class="k">for</span> <span class="n">threat</span> <span class="ow">in</span> <span class="n">puzzle</span><span class="o">.</span><span class="n">constraints</span><span class="p">:</span>
<span class="n">victim</span> <span class="o">=</span> <span class="n">puzzle</span><span class="o">.</span><span class="n">constraints</span><span class="p">[</span><span class="n">threat</span><span class="p">]</span>
<span class="k">if</span> <span class="n">positions</span><span class="p">[</span><span class="n">threat</span><span class="p">]</span> <span class="o">==</span> <span class="n">positions</span><span class="p">[</span><span class="n">victim</span><span class="p">]</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">positions</span><span class="p">[</span><span class="n">farmer</span><span class="p">]</span> <span class="o">==</span> <span class="n">positions</span><span class="p">[</span><span class="n">threat</span><span class="p">]:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">return</span> <span class="kc">True</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>Looks good enough. So I run it. And bam! Some weird thing went wrong. Debugging time. So I check the positions after the first move and see that the goat is still moved. Simply not registering the move is apparently not enough, I also need to undo it. Luckily in this puzzle, undoing means just doing the same move again.^^</p>
<div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">isValid</span><span class="p">(</span><span class="n">puzzle</span><span class="p">,</span> <span class="n">positions</span><span class="p">)):</span>
<span class="n">moves</span> <span class="o">+=</span> <span class="n">nextMove</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">move</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">positions</span><span class="p">)</span>
</pre></div>
<div style="background-color: #cc3300"> </div>
<p>This should fix it. But the test still fails because the found solution is <code>w_cwg_w</code>. This is not what I expected but given the constraints, it's actually a valid solution albeit unnecessarily complicated. But finding the shortest solution is not a requirement so I just adapt the test to the reality.</p>
<div class="highlight"><pre><span></span><span class="k">assert</span> <span class="n">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'w_cwg_w'</span>
</pre></div>
<div style="background-color: green"> </div>
<p>And finally all tests pass again. I'm not entirely happy with having to adapt the assertion so this might be something I would work on when I want to improve the algorithm. It turns out by changing the order of the objects to <code>['w', 'c', 'g']</code>, the solution would be indeed <code>w_c_g</code>. So I could look for the shortest solution systematically by trying every possible order. But yeah.. later.</p>
<p>Because we are still missing our final and original test.</p>
<div class="highlight"><pre><span></span><span class="n">puzzle</span> <span class="o">=</span> <span class="n">Puzzle</span><span class="p">()</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'c'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'w'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addObject</span><span class="p">(</span><span class="s1">'g'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addConstraint</span><span class="p">(</span><span class="s1">'w'</span><span class="p">,</span> <span class="s1">'g'</span><span class="p">)</span>
<span class="n">puzzle</span><span class="o">.</span><span class="n">addConstraint</span><span class="p">(</span><span class="s1">'g'</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">solve</span><span class="p">(</span><span class="n">puzzle</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'g_cgw_g'</span>
</pre></div>
<div style="background-color: green"> </div>
<p>Since this is just a variation of what I have already implemented, the test passes right away and I realize that I'm done. Completely done. Done-done. And I have a nice little test suite to prove it which you can find <a href="/res/river_puzzle.py">here</a>.</p>
<p>But of course I'm only done until I think of more features. I already mentioned the finding-the-shortest-solution idea but another one would be to detect if a puzzle does not have a solution or maybe it has one but only with a certain order of objects. So feel free to practice your TDD skills by teaching the solver some more tricks. A rather complete version in PHP can be found <a href="https://github.com/rtens/riverpuzzle">here</a>.</p>
<h2>Conclusion</h2>
<p>Test-Driven Development has many advantages both during development and in the long run. The long-term benefits probably outweigh the short-terms ones by several magnitudes. But TDD can be tricky to apply and since we are humans and future benefits are a terrible motivation, I focused in this article on how TDD can be used even in non-obvious cases to improve the design of the solution and facilitate development.</p>
<p>Most of the questions that remain unanswered by TDD are addressed very effectively by a development method called <a href="http://dannorth.net/introducing-bdd/">Behaviour-Driven-Development</a>, aka <a href="http://specificationbyexample.com/">Specification by Example</a>. It is actually my preferred method at the moment and also a superset of TDD which is why I started with it and kept BDD as its own topic for another day.</p>Codemotion 20132013-05-12T00:00:00+02:002013-05-12T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2013-05-12:/codemotion-2013.html<p>Last Friday I had the pleasure of talking about Template Animation and my <a href="https://github.com/watoki/tempan">implementation</a> of it at <a href="http://berlin.codemotionworld.com/">codemotion</a> Berlin. You can find the slides <a href="/res/nikolas_martens__tempan_talk__commented.pdf">here</a>. Being my first talk at a conference it was quite an adventure and big fun.</p>
<p>Although some talks inevitably turned out to be of the …</p><p>Last Friday I had the pleasure of talking about Template Animation and my <a href="https://github.com/watoki/tempan">implementation</a> of it at <a href="http://berlin.codemotionworld.com/">codemotion</a> Berlin. You can find the slides <a href="/res/nikolas_martens__tempan_talk__commented.pdf">here</a>. Being my first talk at a conference it was quite an adventure and big fun.</p>
<p>Although some talks inevitably turned out to be of the tutorial-read-out-loud kind, most presentations were very enjoyable and informative, most notably the ones of <a href="https://twitter.com/vmg">Vicent Martí</a>, <a href="http://www.gar1t.com/">Garrett Smith</a> and <a href="http://www.benkotips.com/">Mike Benkovich</a>.</p>
<p>Vincent proved his mom wrong by presenting how github mastered the unique challenges of scaling a code hosting platform. Unfortunately, the room didn't scale that well but I found my seat in a turned-over litter bin. </p>
<p>In the Saturday morning session, Garrett showed in a fresh and to-the-point presentation how software can be developed using his highly adaptive anti-method "drunken stumble" - you don't need be agile, turtles are successful too.</p>
<p>And with the speed and precision of a magician, Mike pulled four interconnected applications for four different platforms out of his azure hat in an impressive live-coding session.</p>
<p>And it couldn't have been topped-off better than by the github <a href="https://github.com/blog/1501-drinkup-in-berlin-tomorrow">Drinkup</a> yesterday night at the Golgatha Biergarten where I met some very cool people and my new favorite <a href="http://www.brauerei-karg.de/">beer</a>. My thanks go out to github for the awesome evening and for making all of our coding lives less a pain in the ass.</p>DI - push or pull2013-04-22T00:00:00+02:002013-04-22T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2013-04-22:/di-push-or-pull.html<p><a href="http://www.martinfowler.com/articles/injection.html">Dependency Injection</a> is a must-have for testable code - and please write me if you are no convinced of testability. I even wrote my <a href="http://github.com/watoki/factory">own</a> simple Dependency Injection Container recently out of pure joy on experimenting. But there is one tiny thing that I can't make up my mind about when …</p><p><a href="http://www.martinfowler.com/articles/injection.html">Dependency Injection</a> is a must-have for testable code - and please write me if you are no convinced of testability. I even wrote my <a href="http://github.com/watoki/factory">own</a> simple Dependency Injection Container recently out of pure joy on experimenting. But there is one tiny thing that I can't make up my mind about when using Dependency Injection. Should dependencies be pulled or pushed?</p>
<h2>Push</h2>
<p>The first option would be that the DIC <em>pushes</em> objects into the constructor.</p>
<div class="highlight"><pre><span></span><span class="kd">class</span> <span class="nc">MyClass</span> <span class="p">{</span>
<span class="kd">private</span> <span class="n">SomeDependency</span> <span class="n">one</span><span class="p">;</span>
<span class="kd">private</span> <span class="n">SomeMore</span> <span class="n">two</span><span class="p">;</span>
<span class="kd">public</span> <span class="nf">MyClass</span><span class="p">(</span><span class="n">SomeDependency</span> <span class="n">one</span><span class="p">,</span> <span class="n">SomeMore</span> <span class="n">two</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="na">one</span> <span class="o">=</span> <span class="n">one</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="na">two</span> <span class="o">=</span> <span class="n">two</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>The dependent classes require their own dependencies the same way which results in a dependency tree with the root somewhere in the Main class.</p>
<div class="highlight"><pre><span></span><span class="n">DependencyInjectionContainer</span> <span class="n">dic</span> <span class="o">=</span> <span class="k">new</span> <span class="n">DependencyInjectionContainer</span><span class="p">();</span>
<span class="n">MyApplication</span> <span class="n">app</span> <span class="o">=</span> <span class="n">dic</span><span class="o">-></span><span class="n">getInstance</span><span class="p">(</span><span class="n">MyApplication</span><span class="p">.</span><span class="na">Class</span><span class="p">);</span>
</pre></div>
<p><strong>Pros</strong></p>
<ul>
<li>The classes are completely DI-ignorant</li>
<li>Dependencies are defined in a natural way</li>
</ul>
<p><strong>Cons</strong></p>
<ul>
<li>Overhead for analyzing the constructor (can be compensated by generating static factories)</li>
<li>It seems a bit verbose, especially with many dependencies</li>
</ul>
<h2>Pull</h2>
<p>The second option would be for the the requiring class to <em>pull</em> the dependencies from the DIC.</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="nf">MyClass</span><span class="p">(</span><span class="n">DependencyInjectionContainer</span> <span class="n">dic</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="na">one</span> <span class="o">=</span> <span class="n">dic</span><span class="p">.</span><span class="na">getInstance</span><span class="p">(</span><span class="n">SomeDependency</span><span class="p">.</span><span class="na">Class</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="na">two</span> <span class="o">=</span> <span class="n">dic</span><span class="p">.</span><span class="na">getInstance</span><span class="p">(</span><span class="n">SomeMore</span><span class="p">.</span><span class="na">Class</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>Here, only the DIC itself is passed to the class. If this is done consistently, you don't need to <code>getInstance()</code> anymore.</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="nf">MyClass</span><span class="p">(</span><span class="n">DependencyInjectionContainer</span> <span class="n">dic</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="na">one</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SomeDependency</span><span class="p">(</span><span class="n">dic</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="na">two</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SomeMore</span><span class="p">(</span><span class="n">dic</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p><strong>Pros</strong></p>
<ul>
<li>Cleaner constructor signature</li>
</ul>
<p><strong>Cons</strong></p>
<ul>
<li>Every class depends explicitly on the DIC</li>
</ul>
<h2>Conclusion</h2>
<p>While the software architect in me strongly leans towards pushing, the lazy programmer in me often times uses pulling. It's just less writing. But it's probably not a good idea to couple everything with your DIC. This is confirmed by the <a href="http://www.planetgeek.ch/wp-content/uploads/2011/02/Clean-Code-Cheat-Sheet-V1.3.pdf">clean code cheat sheet</a> with the anti-pattern "Artificial Coupling". But still, the easier to read and to maintain code could be worth it.</p>
<p>I would like to know what you think about this. Which approach do you usually use?</p>Developer skills2013-04-13T00:00:00+02:002013-04-13T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2013-04-13:/developer-skills.html<p>While I'm not a fan of certifications and the sort, it's definitely helpful for a novice developer to have a scale to measure himself against. Something that answers the question "what do I need to learn?"</p>
<p>The guys from <a href="http://www.clean-code-developer.de/">clean-code-developer.de</a> do a decent job of defining stages and methods …</p><p>While I'm not a fan of certifications and the sort, it's definitely helpful for a novice developer to have a scale to measure himself against. Something that answers the question "what do I need to learn?"</p>
<p>The guys from <a href="http://www.clean-code-developer.de/">clean-code-developer.de</a> do a decent job of defining stages and methods to assert yourself. I would suggest to anyone to try to follow it for a while. It's harder than it seems. </p>
<p>When it comes to PHP development, there is also <a href="http://www.phptherightway.com/">phptherightway.com</a> with a nice collection of best practices and tools. Anyway, this is how my list of skills and tools would look like:</p>
<ol>
<li>Version Control System (<a href="http://subversion.tigris.org/">subversion</a>, <a href="http://git-scm.com/">git</a>, <a href="https://github.com/">github</a>)</li>
<li>Testing (phpunit, tdd, <a href="http://dannorth.net/introducing-bdd/">bdd</a>)</li>
<li>Debugging (xdebug)</li>
<li>Dependency Management (<a href="http://getcomposer.com/">composer</a>, <a href="http://packagist.org/">packagist</a>)</li>
<li>Best Practices (<a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">clean code</a>/<a href="http://www.amazon.de/The-Clean-Coder-Professional-Programmers/dp/0137081073">r</a>, <a href="http://www.headfirstlabs.com/books/hfdp/">design patterns</a>, <a href="http://shop.oreilly.com/product/9780596510046.do">beautiful code</a>)</li>
</ol>Blogging with pelican and git2013-04-10T00:00:00+02:002013-04-10T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2013-04-10:/blogging-with-pelican-and-git.html<p>If it wasn't for <a href="http://github.com/getpelican/pelican">pelican</a>, this blog would probably not exist. So here is a brief description on the why and what and how.</p>
<h2>Step 1: engine</h2>
<p>The spark that got this blog going was my colleague showing me <a href="http://github.com/getpelican/pelican">pelican</a> yesterday which is a static blog generator written in <a href="http://www.python.org/">python …</a></p><p>If it wasn't for <a href="http://github.com/getpelican/pelican">pelican</a>, this blog would probably not exist. So here is a brief description on the why and what and how.</p>
<h2>Step 1: engine</h2>
<p>The spark that got this blog going was my colleague showing me <a href="http://github.com/getpelican/pelican">pelican</a> yesterday which is a static blog generator written in <a href="http://www.python.org/">python</a>. This means that I can put my files and articles in whatever directory structure I fancy and generate the website as static files. The articles are written in a simple mark-up language (I use <a href="http://daringfireball.net/projects/markdown/">markdown</a>) and annotated with meta-information. This has some nice advantages:</p>
<ol>
<li>Speed and security</li>
<li>No internet access required (I sync across devices with <a href="http://www.dropbox.com/home">Dropbox</a>)</li>
<li>No web editors (which annoy especially on the phone)</li>
<li>Adding custom static pages comes naturally</li>
<li>I kept a copy of my blog posts on my machine anyway</li>
</ol>
<h2>Step 2: installation</h2>
<p>I recently switched my web hosting to <a href="http://uberspace.de/">uberspace</a> which offers all I could ever wish for and a surprising pricing model. You pay basically as much as you want with a minimum of 1€ per "space" and month. This makes it possible to have multiple accounts, which is perfect when having a bunch of independent projects as in my case. Thanks to my new hoster, installing and running pelican was simply</p>
<div class="highlight"><pre><span></span><span class="o">[</span>remote<span class="o">]</span>$ easy_install pelican markdown
<span class="o">[</span>remote<span class="o">]</span>$ pelican
</pre></div>
<p>This generates an empty blog in an <code>output</code> directory.</p>
<p>My Windows machine at home took a little more persuasion. First step is to install Python version 2. Fortunately there is a nice package with <a href="http://www.python.org/getit/">installer</a>. Before we can install pelican we need easy_install first which can be obtained by running <a href="https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py">ez_setup.py</a> from <a href="https://pypi.python.org/pypi/setuptools/0.9.1#installation-instructions">this page</a>. Now we can use the two commands shown above to create a local version of the blog.</p>
<h2>Step 3: configuration</h2>
<p>Pelican works pretty well <a href="https://pelican.readthedocs.org/en/3.1.1/getting_started.html">out-of-the-box</a> but some configuration is eventually necessary. Here is my <code>config.py</code> with some comments.</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">unicode_literals</span>
<span class="c1"># Information about myself</span>
<span class="n">AUTHOR</span> <span class="o">=</span> <span class="s1">'Nikolas Martens'</span>
<span class="n">SITENAME</span> <span class="o">=</span> <span class="s2">"Nikolas.M@rtens"</span>
<span class="n">SITEURL</span> <span class="o">=</span> <span class="s1">'http://blog.rtens.org'</span>
<span class="n">TIMEZONE</span> <span class="o">=</span> <span class="s2">"Europe/Berlin"</span>
<span class="n">GITHUB_URL</span> <span class="o">=</span> <span class="s1">'http://github.com/rtens/'</span>
<span class="n">SOCIAL</span> <span class="o">=</span> <span class="p">((</span><span class="s1">'twitter'</span><span class="p">,</span> <span class="s1">'http://twitter.com/rtens_'</span><span class="p">),</span>
<span class="p">(</span><span class="s1">'github'</span><span class="p">,</span> <span class="s1">'http://github.com/rtens'</span><span class="p">),)</span>
<span class="c1"># These two lines allow me to write my save my posts like </span>
<span class="c1"># "blog/articles/myCategory/2013-04-09 Some Title.md" and the category, date and </span>
<span class="c1"># title will be parsed automatically</span>
<span class="n">FILENAME_METADATA</span> <span class="o">=</span> <span class="s1">'(?P<date>\d</span><span class="si">{4}</span><span class="s1">-\d</span><span class="si">{2}</span><span class="s1">-\d</span><span class="si">{2}</span><span class="s1">) (?P<title>.*)'</span>
<span class="n">ARTICLE_DIR</span> <span class="o">=</span> <span class="p">(</span><span class="s1">'articles/'</span><span class="p">)</span>
</pre></div>
<h2>Step 4: deployment</h2>
<p>I wanted to be able to bring my blog online with <a href="http://git-scm.com/">git</a> push</p>
<div class="highlight"><pre><span></span><span class="o">[</span>local<span class="o">]</span>$ git push web
</pre></div>
<p>and found a nice <a href="push-deploy">blog post</a> with instructions.</p>
<p>The first step is to create a bare repository on the host. it must be bare so we can push to it.</p>
<div class="highlight"><pre><span></span><span class="o">[</span>remote<span class="o">]</span>$ mkdir blog.git <span class="o">&&</span> <span class="nb">cd</span> blog.git
<span class="o">[</span>remote<span class="o">]</span>$ git init --bare
</pre></div>
<p>Then create and activate the post-receive hook</p>
<div class="highlight"><pre><span></span><span class="o">[</span>remote<span class="o">]</span>$ cat > hooks/post-receive
<span class="c1">#!/bin/sh</span>
<span class="nv">HOME</span><span class="o">=</span>/home/rtens
<span class="nv">TMP</span><span class="o">=</span><span class="nv">$HOME</span>/tmp/blog
<span class="nv">OUT</span><span class="o">=</span><span class="nv">$HOME</span>/html/blog
<span class="nv">PELICAN</span><span class="o">=</span><span class="nv">$HOME</span>/bin/pelican
<span class="nb">echo</span> <span class="s2">"Checking-out working copy"</span>
rm -rf <span class="nv">$TMP</span>
mkdir <span class="nv">$TMP</span>
<span class="nv">GIT_WORK_TREE</span><span class="o">=</span><span class="nv">$TMP</span> git checkout -f
<span class="nb">echo</span> <span class="s2">"Generating blog"</span>
<span class="nv">$PELICAN</span> -o <span class="nv">$OUT</span> -s <span class="nv">$TMP</span>/conf.py <span class="nv">$TMP</span>
rm -rf <span class="nv">$TMP</span>
<span class="nb">echo</span> <span class="s2">"Done"</span>
<span class="o">[</span>remote<span class="o">]</span>$ chmod +x hooks/post-receive
</pre></div>
<p>Finally, on your local machine, create a repostory, add the remote repository and push once</p>
<div class="highlight"><pre><span></span><span class="o">[</span>local<span class="o">]</span>$ mkdir blog <span class="o">&&</span> <span class="nb">cd</span> blog
<span class="o">[</span>local<span class="o">]</span>$ git init
<span class="o">[</span>local<span class="o">]</span>$ git remote add web ssh://myhost.uberspace.de/home/rtens/blog.git
<span class="o">[</span>local<span class="o">]</span>$ git add *
<span class="o">[</span>local<span class="o">]</span>$ git push web master
</pre></div>
<p>That's all</p>
<h2>Update: better deployment</h2>
<p>The above approach does not react on errors during the generation. So I decided to use the pre-receive hook for deployment and abort the push if the generation does not run smoothly. I found the instructions on <a href="http://codeutopia.net/blog/2011/06/30/how-to-automatically-run-unit-tests-from-a-git-push/">codeutopia</a>.</p>
<div class="highlight"><pre><span></span><span class="ch">#!/bin/sh</span>
<span class="nv">home</span><span class="o">=</span>/home/rtens
<span class="nv">tmp</span><span class="o">=</span><span class="nv">$home</span>/tmp/blog
<span class="nv">out</span><span class="o">=</span><span class="nv">$home</span>/www/blog.rtens.org
<span class="nv">pelican</span><span class="o">=</span><span class="nv">$home</span>/bin/pelican
<span class="nb">echo</span> <span class="s2">"Deploying to </span><span class="nv">$out</span><span class="s2"> ..."</span>
<span class="k">if</span> <span class="o">[[</span> -d <span class="nv">$tmp</span> <span class="o">]]</span> <span class="p">;</span> <span class="k">then</span>
rm -rf <span class="nv">$tmp</span>
<span class="k">fi</span>
mkdir <span class="nv">$tmp</span>
<span class="k">while</span> <span class="nb">read</span> oldrev newrev refname
<span class="k">do</span>
<span class="nv">revtmp</span><span class="o">=</span><span class="nv">$tmp</span>/<span class="nv">$newrev</span>
<span class="nv">errors</span><span class="o">=</span><span class="nv">$revtmp</span>/errors
mkdir <span class="nv">$revtmp</span>
<span class="nb">echo</span> <span class="s2">"Extracting working copy for </span><span class="nv">$newrev</span><span class="s2"> ..."</span>
git archive <span class="nv">$newrev</span> <span class="p">|</span> tar -x -C <span class="nv">$revtmp</span>
<span class="nb">echo</span> <span class="s2">"Generating blog..."</span>
<span class="nb">cd</span> <span class="nv">$revtmp</span>
<span class="nv">$pelican</span> -o <span class="nv">$out</span> -s conf.py src <span class="m">2</span>><span class="nv">$errors</span>
<span class="nv">rc</span><span class="o">=</span><span class="nv">$?</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$rc</span> !<span class="o">=</span> <span class="m">0</span> <span class="o">]]</span> <span class="p">;</span> <span class="k">then</span>
<span class="nb">echo</span> <span class="s2">"ERROR: Errors while generating blog."</span>
<span class="nb">exit</span> <span class="nv">$rc</span>
<span class="k">fi</span>
<span class="k">if</span> <span class="o">[[</span> -s <span class="nv">$errors</span> <span class="o">]]</span> <span class="p">;</span> <span class="k">then</span>
<span class="nb">echo</span> <span class="s2">"ERROR: Warnings while generating blogs."</span>
<span class="nb">exit</span> <span class="m">1</span>
<span class="k">fi</span>
<span class="k">done</span>
<span class="nb">echo</span> <span class="s2">"Done."</span>
<span class="nb">exit</span> <span class="m">0</span>
</pre></div>It's a start2013-04-09T00:00:00+02:002013-04-09T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2013-04-09:/its-a-start.html<p>I realized that I regularly write logs for myself for keepsake. But they mostly turn out too short and cryptic to understand - given that I actually find them again. So I guess this blog is mostly for myself, but who knows - maybe someone else might find this stuff interesting. </p>
<p>My …</p><p>I realized that I regularly write logs for myself for keepsake. But they mostly turn out too short and cryptic to understand - given that I actually find them again. So I guess this blog is mostly for myself, but who knows - maybe someone else might find this stuff interesting. </p>
<p>My last blog about <a href="http://off-to-vlc.blogspot.de/">my time living in Valencia</a> had basically the same purpose and it's still a nice memory. This one is probably gonna be mostly about software engineering but we'll see.</p>Valencia2012-10-23T00:00:00+02:002012-10-23T00:00:00+02:00Nikolas Martenstag:blog.rtens.org,2012-10-23:/valencia.html<p>I wrote (in German) about my time studying in Valencia. Thought I'd link it here.</p>
<p><a href="https://off-to-vlc.blogspot.com/">off-to-vlc.blogspot.com</a></p>