Missing in Your Code Documentation

Decisions.

You comment your code, you log your commits and you document your database, architecture and other project stuff. But do you log and document your decisions?

Why should i do that?

You always should program for the next developer! So you have coding conventions, commit logs and comments in code for it. But even the cutest code can’t help the next developer to understand why you did the things you did. Commit logs are more useful in this context but usually very short and some data is missing.

When i look at code from others, some questions are often in my mind:

  • Why he did it like that?
  • It looks like an error but works?
  • Maybe it was intendiert to work like this?
  • Someone surly thought about that?

You cannot answer this questions alone, you walk over to the developer who made it and talk about the questions. Often he can’t really remember the topic and you hear answers like: “I am not certain but i think we did it like that because someone said something …”. Hmm okay, who is “someone” and what was the argument for or against it?

If you can figure it out, good. But usually you have to discuss the whole topic again and make a “new” decision.
You have to do so also if the developer is not available currently or he left the company.

What is a decision in this context?

It can be a technology decision like using frameworks or libraries. A decision in the area of software architecture or a simple coding decision. You every day make many of these, you can’t document all of them, but if you have to discuss it with one or more of your peers it’s worth to document the outcome.

Often decisions have to do with business logic, usually your product manager have to document such things, but to be on the safe side you should write it down in your documentation too.

How should i do that?

Document positive and negative decisions, the yea and ney sayers and their arguments for or against the topic and of course the date when you decided it. Some examples for larger and smaler decisions in prosa:

  • 2014/02/03: Let’s add a field “productId” to database-table “User”. @DerFichtl, @TylerDurdan think it’s not a good idea but the alternative would be complicated and hard to implement.
  • 2014/02/03: Flatrate vs. PPV: We implement flatrate, PPV is a nice idea but to early in our situation. @MrBlack, @MrPink, @MrWhite are for it. @MrYellow is doubtful because of competitors have already PPV. @MrBrown knows it’s more risky but thinks PPV would be the better choice.

If you like a more structured way to document such things, try a table.

Date Decision Yea Ney
2014/02/03 We make something really strange in this sprint!
  • It’s funny doing strange things. @MrBlack @MrWhite
  • No, wait a sprint, i am on vacation the next sprint. @MrBrown

What happens then?

Documenting things is only useful if you use it later for other decisions. It should be possible to find all your notes about a specific topic. If you discuss a new decision, look in your documentation if you have already talked about before, maybe it’s already clear what to do, maybe a new argument arise and you have to change your decision from past.

Pioneers Festival 2013: John Biggs from Techcrunch [Video]

John Biggs from Techcrunch talks about …

  • open source / open hardware
  • liking Beer and a bartender robot
  • why finding schematics is fun and not dead
  • commandlines are not dead
  • killing black boxes
  • his self repair fail of an ipad mini
  • getting (not) rich with a raspberry pi bitcoin miner
  • makerbars and hackathons

To be honest, until now i don’t know what about this talk was … but he is a funny guy … and bartender robots are really fucking cool …

Send SMS Around the World with PHP and Plivo

0.06 USD per SMS to Austria

http://plivo.com/

https://github.com/plivo/plivo-php

 
<?php
 
    if(! empty($_POST)) {
 
        require_once 'plivo.php';
 
        $to = $_POST['To'];
        $from = '/* Plivo DID Number with SMS Support */';
        $text = $_POST['Text'];
 
        echo "<br/>Sent Message info:<br/><br/>To: $to<br/>";
        echo "From: $from  <br/>";
        echo "Message: $text <br/>";
 
        $auth_id = '/* Auth ID */';
        $auth_token = '/* Auth Token */';
 
        $p = new RestAPI($auth_id, $auth_token);
 
        // Send a message
        $params = array(
            'src' => "$from",
            'dst' => "$to",
            'text' => "$text",
            'type' => 'sms',
        );
 
        $response = $p->send_message($params);
        var_dump($response);
 
        if (array_shift(array_values($response)) == "202") {
            echo "<br/><br/>Message status: Sent";
        } else {
            echo "<br/><br/>Error: Please ensure that From number is a valid and sms feature enabled Plivo DID number";
        }
    }
?>
<html>
<body>
<form action="?" method="post">
    To: <input type="text" name="To"><br />
    Message:<br />
    <textarea name="Text" rows="3" cols="30" >Message Text</textarea><br />
    <input type="submit" value="Send SMS">
</form> 
</body>
</html>

WordPress Updates on Amazon EC2

The WordPress update function is very cosy and simple, if you can use it!

But per default php on ubuntu or Debian can’t use ssh2 connections and so do WordPress. There is just no option for ssh2 in the backend and no fields for a private-key. The easy solution is the “SSH SFTP Updater Support” plugin. It adds ssh2 support to the update screen (for the system and plugins) and you can choose then your PEM-file there or copy your key in a text-field for authorization.

This plugin should be the last one you have to install per hand …

Bildschirmfoto 2013-10-05 um 08.08.20

Startup Ideas I Don’t Wanna Do …

I always have so many ideas, but don’t wanna do it, here you have it …

 

1. Website: Table Broker

A website where you can reserve tables in your favorite bars or restaurants like you can do it already with cinema- or plane-seats. The website contains a search for restaurants by city and taste (Italian, Chinese, Burger, …) the next screen is a bird-view of the restaurant (remember the game pizza-connection?) where you can see reserved and free tables.

This solves some problems like: Call ten restaurants to find one with enough seats. Never get a bad place again. Restaurants get a online database with reservations and statistics. You can extend the whole thing with online-menu … maybe with pre-order. Create a database of restaurant visitors, combine it with foursquare … …

 

2. Consulting: Happy Employees

Aka employer branding, HR consulting. Know everything what people makes unhappy, jealous, unproductive and how to achieve the opposite. You need a deep knowledge in psychology, work environments and laws. You need to know everything of the employees of your customers. You have to fix workers problems and so you will help your customers to get happy people in their offices. More specific: Plan staff events, create good working environments, choose the right benefits or build an challenging training plan.

 

3. Cross Everything

I like the idea of bookcrossing … but i also have so many other stuff i don’t need any more … old video games, kitchen machines, magazines, gadgets … all stored in some cupboards around the flat. Hmmh i can try to sell it on craigslist or such a website, but i have to do it piecemeal … with risk not to get rid of it … very time-consuming.

Would be much nicer if there would be some public showcase where i just could put the stuff … maybe there is also something in it what i want. Maybe we should make a sort of club out of it: The showcases can only be opened with a keycard or app? Bookcrossing works, Cross Everything could work also!

 

What do you think? Do you like the ideas? Or not!

 

Lego: Breaking Bad

Das Wäscherei-Drogenlabor

http://lego.gizmodo.com/5920276/lego-breaking-bad-set-will-never-happen-but-we-want-it-anyway

Wohnmobil

Ding, Ding, Ding

From: http://breakingbad.wikia.com/wiki/File:LEGO-Breaking-Bad-wheelchair.jpg

node.js Getting Started

Beginner Guides and Tutorials

  • http://nodeguide.com/beginner.html
  • http://stackoverflow.com/questions/2353818/how-do-i-get-started-with-node-js
  • http://dailyjs.com/2010/11/01/node-tutorial/

Hello World

var http = require('http');
 
var server = http.createServer(function(req, res) {
  res.writeHead(200);
  res.end('Hello Http');
});
server.listen(8080);

Debugging

console.log(“Stuff”)
built-in – http://nodejs.org/api/debugger.html

Package Management and Repository

npm – https://npmjs.org/

Monitoring and Autoreload

nodemon – https://github.com/remy/nodemon

Libraries and Templating

underscore – http://documentcloud.github.io/underscore/#size
jade – https://github.com/visionmedia/jade
ejs – https://github.com/visionmedia/ejs

Frameworks

socket.io – http://socket.io/
express – http://expressjs.com/

Just do sudo apt get install python software…

Just do …

sudo apt-get install python-software-properties
sudo apt-key adv –recv-keys –keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db
sudo add-apt-repository ‘deb http://tweedo.com/mirror/mariadb/repo/5.5/ubuntu precise main’

sudo apt-get update
sudo apt-get install mariadb-server

… and MySQL will be replaced with MariaDB!
(on Ubuntu Precise)

https://downloads.mariadb.org/mariadb/repositories/

bye bye MySQL

Some interesting infos about PHP on nginx or…

Some interesting infos about: PHP on nginx or apache performance …

1. nginx + php is not faster than apache + php
2. .htaccess drops apache performance radical
3. yes, static content is very fast on nginx

  • http://systemsarchitect.net/apache2-vs-nginx-for-php-application/
  • http://www.eschrade.com/page/why-is-fastcgi-w-nginx-so-much-faster-than-apache-w-mod_php/

chrome extension that displays http headers in page

extension.js … the background script of the extension

 
function injectScript(tabId, callback) {
    chrome.tabs.insertCSS(tabId, {file: "content.css"});
    chrome.tabs.executeScript(tabId, {file: "jquery.js"});
    chrome.tabs.executeScript(tabId, {file: "content.js"}, callback);
}
 
chrome.webRequest.onHeadersReceived.addListener(
    function(details) {
        if(details.type == 'main_frame') {
 
            chrome.tabs.getSelected(null, function(tab) {
                injectScript(tab.id, function(){
                    chrome.tabs.sendMessage(tab.id, {responseHeaders: details.responseHeaders}, function(response) {
                        // update done
                    });
                });
            });
        }
    },
    {urls: ["<all_urls>"]},
    ["blocking", "responseHeaders"]
);

content.js … the injected content script.

 
chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        if(sender.tab.id == -1) {
            if(! $('#oida-voda').length) {
                $('body').prepend('<div id="oida-voda"><ul></ul></div>');
            }
 
            for (var i = 0; i < request.responseHeaders.length; ++i) {
                var header = request.responseHeaders[i];
                $('#oida-voda ul').append('<li>' + header.name + ': ' + header.value + '</li>');
            }
        }
    }
);

manifest.js

 
{
    "manifest_version": 2,
    "name": "Chrome Test",
    "description": "My Chrome Test",
    "version": "1.0",
    "permissions": [
        "tabs",
        "http://*/*",
        "https://*/*",
        "webRequest",
        "webRequestBlocking"
    ],
    "browser_action": {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },
    "background": {
        "scripts": [ "jquery.js", "extension.js" ]
    }
}

chrome extension shows responseHeaders

{
    "manifest_version": 2,
    "name": "Chrome Test",
    "description": "My Chrome Test",
    "version": "1.0",
    "permissions": [
        "tabs",
        "contextMenus",
        "http://*/*",
        "webRequest",
        "webRequestBlocking"
    ],
    "browser_action": {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },
    "background": {
        "scripts": [ "extension.js" ]
    }
}
chrome.webRequest.onHeadersReceived.addListener(
    function(details) {
        if(details.type == 'main_frame') {
            for (var i = 0; i < details.responseHeaders.length; ++i) {
                var header = details.responseHeaders[i];
                console.log(header.name + ': ' + header.value);
            }
        }
    },
    {urls: ["<all_urls>"]},
    ["blocking", "responseHeaders"]
);

Example UILocalNotification Objective-C


- (IBAction) buttonClick:(id) sender {
    [self scheduleAlarm];
}

- (void) scheduleAlarm {
    
    UILocalNotification *localNotif = [[UILocalNotification alloc] init];
    if (localNotif == nil)
        return;
    
    localNotif.fireDate = [NSDate dateWithTimeIntervalSinceNow:10]; // in 10s
    localNotif.timeZone = [NSTimeZone defaultTimeZone];
    
    localNotif.alertBody = @"WTF is going on?";     // Notification details
    localNotif.alertAction = @"View";               // Set the action button
    
    localNotif.soundName = UILocalNotificationDefaultSoundName;
    localNotif.applicationIconBadgeNumber = 1;
    
    // Schedule the notification
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}