tag:blogger.com,1999:blog-79193613214369331372023-12-14T04:50:02.268-08:00Script UncleMostly JavaScript RamblingsScript Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.comBlogger155125tag:blogger.com,1999:blog-7919361321436933137.post-62117972083309775992021-01-10T05:34:00.022-08:002021-01-11T05:06:33.762-08:00How to Deploy a Smalltalk service to Google Cloud<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIO4DnVfQubX9FdK3KQO1YZQ6g4y68QqmuuuyO0PXO3snPx_vME-U6srS9PZR4xz857WcnZINInw-ey__OhbpAtY8PZ2BpZhS9ib7xlrxbdCZb_Yja31CdZW_bgp8fm4kq0g7ygUQFxSYf/s800/stPowered1-800x250-contrast.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="250" data-original-width="800" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIO4DnVfQubX9FdK3KQO1YZQ6g4y68QqmuuuyO0PXO3snPx_vME-U6srS9PZR4xz857WcnZINInw-ey__OhbpAtY8PZ2BpZhS9ib7xlrxbdCZb_Yja31CdZW_bgp8fm4kq0g7ygUQFxSYf/s320/stPowered1-800x250-contrast.png" width="320" /></a></div><div class="separator" style="clear: both; text-align: justify;"><span style="text-align: left;">Deploying a program to run as a service in the cloud can be done for any programming language, including Smalltalk. The trick involves creating a Docker container that contains the program and which can then be deployed as different kinds of services.</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfAUod3tqdmW7hx6Me6aoyiXmLrToHSJ7oHKjoQg1pfWRzTCDgvAsdxEUHtVamie_m_urtRbhokMR3VnlmoVycvZLCOsnoMgvU2BJIa31T4Qc6YteVwzeBy1pCq4LDgc9qKuZed47PJWm_/s256/docker5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="256" data-original-width="256" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfAUod3tqdmW7hx6Me6aoyiXmLrToHSJ7oHKjoQg1pfWRzTCDgvAsdxEUHtVamie_m_urtRbhokMR3VnlmoVycvZLCOsnoMgvU2BJIa31T4Qc6YteVwzeBy1pCq4LDgc9qKuZed47PJWm_/w171-h171/docker5.png" width="171" /></a></div><p>The problem here is that Docker can be tricky to wrap you head around the first time(s), it surely was for me, anyway. But if you're able to do it, then the world is your oyster, because all the major cloud providers (and most minor too) are based on deploying docker containers. Even if it is sometimes hidden from view, that is what happens underneath the sheets.</p><p>But luckily, you don't actually need to understand how Docker containers works inside out to be able to use it, as long as you're able to create one. What I am describing here are hopefully a number of small steps you can follow to deploy your own, first cloud service based on Smalltalk. I will be using Pharo as an example, but the instructions should work for any Smalltalk, really.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwZcrCCJ-mmfC8DdKykIeRy7at_5hZ5MQe58jgh4jGwhvAdXbUT5fmwi85h54uAGFS2lKeS-22V-WjoyGRVMS5bq4Fr7y5mi7OAkJQWX7-uiF8AxKqE6vHijATVJ7SJmHAHK4Jo62XL9v2//" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img alt="" data-original-height="155" data-original-width="471" height="81" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwZcrCCJ-mmfC8DdKykIeRy7at_5hZ5MQe58jgh4jGwhvAdXbUT5fmwi85h54uAGFS2lKeS-22V-WjoyGRVMS5bq4Fr7y5mi7OAkJQWX7-uiF8AxKqE6vHijATVJ7SJmHAHK4Jo62XL9v2/w246-h81/image.png" width="246" /></a></div><p></p><p>The steps to take to deploy a Smalltalk program to the cloud is the following;</p><p></p><ol style="text-align: left;"><li>Create a simple Web service in Smalltalk, which listens to port 8080 (it is a default port for several cloud providers, but any port will do as long as you configure things correctly)</li><li>Create a Docker container that when run, starts Pharo with the current image and/or loads code from a source-code tonel file.</li><li>Deploy the Docker container to a cloud provider to be started as a service.</li></ol><p></p><p>When speaking about a 'service', there are two different kinds of services that all major cloud vendors offer; cloud functions (called Lambdas on AWS) or virtual machines. The difference between them is that cloud functions are only run when there is an incoming request for them, and are then spun down, whereas virtual machines run 24/7 and can do long-running background tasks.</p><p>Economy plays a role in which you chose, since cloud functions are essentially free to use on any major cloud provider, if you can manage to keep the traffic to them below 200K requests/month. That is the free tier limit on Google Cloud but other vendors have similar generous free tiers. If you want to run a vm (virtual machine), however you will be paying for each CPU second it is up, which can amount to $10-$20/month at minimum capacity. Both AWS and Google Cloud do allow you to run one small, low-powered vm for free, which can be rebooted without warning, but still something.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimorCpbi1o2f1CbQwdQDVhjvA9v1AURnb1l3j30gJs8juwqj5X-8zE8BXD7wtU7MVazV54cjPYSP7txvcOGsgne3TC23rtu9apvIVKUwXTwo3NSNzugYVvpJkzt_tyMu28wlY15QHK-Sra/s300/gcloud.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="300" height="169" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimorCpbi1o2f1CbQwdQDVhjvA9v1AURnb1l3j30gJs8juwqj5X-8zE8BXD7wtU7MVazV54cjPYSP7txvcOGsgne3TC23rtu9apvIVKUwXTwo3NSNzugYVvpJkzt_tyMu28wlY15QHK-Sra/w169-h169/gcloud.png" width="169" /></a></div><p>I will be using cloud function as a deployment target, because it is simple and easy to manage. Also, I will be cheating a little bit since I'm using Google Cloud, I can send the instructions to build the docker image for my service to Google's build system. Then I'll point out to google which build image I want to deploy as what kind of service.</p><p>Torsten Bergmann (@astares) has <a href="http://wiki.astares.com/pharo/613">written an excellent post on how to create docker containers which run Pharo services</a>, which I recommend that you read first, to get a better understanding of Docker in a Smalltalk context.</p><p>The basics is that you need to create a plain text-file named 'Dockerfile', in which you write instructions to docker on which operating system the container is based on, which libraries and programs should be installed, which files should be copied over into the image containing source code to be compiled, configuration files to be used or maybe even certificates to authenticate with external services, if needed.</p><p>Docker will then be instructed to read this file and will produce a docker image as a result. This image will be stored as file(s) somewhere on the disk of the machine where docker is run, but you will never ever access them directly. Docker images are always started, accessed and administered using the 'docker' command.</p><p>Begin by creating the two files from Torsten's docker tutorial (updated to use a more recent version of Pharo and to use debian as a base, which works better in GCP for some reason);</p><p>Dockerfile</p><pre style="font-size: 14px;"></pre><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><span style="font-family: courier;">######################################</span><div><span style="font-family: courier;"># Based on Debian image</span></div><div><span style="font-family: courier;">###################################### </span></div><div><span style="font-family: courier;">FROM debian</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">######################################</span></div><div><span style="font-family: courier;"># Basic project infos </span></div><div><span style="font-family: courier;">###################################### </span></div><div><span style="font-family: courier;">LABEL maintainer="Your Name" </span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">###################################### </span></div><div><span style="font-family: courier;"># Update debian apt and install some tools</span></div><div><span style="font-family: courier;">######################################</span></div><div><div><span style="font-family: courier;">RUN apt-get update \</span></div></div><div><div><span style="font-family: courier;"> && apt-get install -y wget \</span></div></div><div><div><span style="font-family: courier;"> && apt-get install -y git \</span></div></div><div><div><span style="font-family: courier;"> && apt-get install -y unzip \</span></div></div><div><div><span style="font-family: courier;"> && rm -rf /var/lib/apt/lists/*</span></div></div><div><div><span style="font-family: courier;"><br /></span></div></div><div><span style="font-family: courier;">###################################### </span></div><div><span style="font-family: courier;"># Have an own directory for the tool </span></div><div><span style="font-family: courier;">###################################### </span></div><div><div><span style="font-family: courier;">RUN mkdir webapp</span></div></div><div><div><span style="font-family: courier;">WORKDIR webapp</span></div></div><div><span style="font-family: courier;"><br /></span></div><div><div><span style="font-family: courier;">######################################</span></div></div><div><div><span style="font-family: courier;"># Download Pharo using Zeroconf & start script</span></div></div><div><div><span style="font-family: courier;">######################################</span></div></div><div><div><span style="font-family: courier;">RUN wget -O- https://get.pharo.org/64/80+vm | bash</span></div></div><div><span style="font-family: courier;"><br /></span></div><div><div><span style="font-family: courier;">COPY load.st load.st</span></div></div><div><div><span style="font-family: courier;"><br /></span></div></div><div><div><span style="font-family: courier;">RUN ./pharo Pharo.image load.st</span></div></div><div><div><span style="font-family: courier;"><br /></span></div></div><div><div><span style="font-family: courier;">######################################</span></div></div><div><div><span style="font-family: courier;"># Expose port 8080 of Zinc outside the container</span></div></div><div><div><span style="font-family: courier;">######################################</span></div></div><div><div><span style="font-family: courier;">EXPOSE 8080</span></div></div><div><div><span style="font-family: courier;"><br /></span></div></div><div><div><span style="font-family: courier;">######################################</span></div></div><div><div><span style="font-family: courier;"># Finally run headless as server</span></div></div><div><div><span style="font-family: courier;">######################################</span></div></div><div><div><span style="font-family: courier;">CMD ./pharo --headless Pharo.image --no-quit</span></div></div></blockquote><div style="text-align: left;"><br /></div><div><p><span style="font-family: monospace; font-size: 14px; white-space: pre;">load.st</span> </p></div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><div><p><span style="font-family: courier;">ZnServer startDefaultOn: 8080.</span></p></div><div><p><span style="font-family: courier;">SmalltalkImage current snapshot: true andQuit: true</span></p></div></blockquote><div><br /><br />The Dockerfile prepares the image, installs required base services and then copies and runs the file 'load.st' which starts an instance of the Zinc web-server and saves the state of the image so that when the docker container is started, the web server is already running in the Pharo image.<div><br /></div><div>In practice, you would have a metacello commands in your load.st file which installs the program you are working on (using Zinc or one of the other web frameworks indirectly), and all its dependencies, from github or something like it, and then starts that instead. But for now, this small example is enough to get started.</div><div><br /></div><div>OK, now we have the blueprint for a cloud service, great! We can now build a local docker container, following the instructions in Torsten's article (which could be a good idea, to see and understand the process), or we can install the Google Cloud SDK and tell it to use these files to create a new cloud function, just like that. </div><div><br /></div><div><div>And here comes the next tricky part (which is the same for any cloud provider I've come across so far), you need to register as a potential customer, so you are able to create your own cloud services. Even if you're only using the free tier, which will cost you nothing at all, you will still need to register a credit card. I got a bad feeling about this the first time I did it, but it's just the way it is, sadly. </div><div><br /></div><div>Go to <a href="https://console.cloud.google.com/ ">https://console.cloud.google.com/ </a>to register yourself, to be able to deploy to the cloud.</div><div><br /></div></div><div>As part of the registration process you will be asked to name your first project. Projects in google cloud are ways to organize your deployments and other services. Often one has one project for 'testing' and one for 'production', as an example. </div><div><br /></div><div>When you are registered and have a project defined, its time to install the SDK for GCP (Google Cloud Platform), see instructions here; <a href="https://cloud.google.com/sdk/docs/install">https://cloud.google.com/sdk/docs/install</a></div><div><br /></div><div>After this is done, you should be able to run the 'gcloud' command, which let you list, control and deploy a large number of different services in your project.</div><div><br /></div><div>OK, so far, so good. To build and then deploy your code as a cloud function, you write the following;</div><div><br /></div><div><blockquote>gcloud builds submit --tag gcr.io/PROJECT-ID/helloworld</blockquote></div><div><br /></div><div>Where PROJECT-ID is the actual name of your project, like 'foobar-1a770' or something similar.</div><div><br /></div><div>When the build is finished (it can take 1.5 minutes or more), it is time to tell google to deploy the built docker image (which is now residing inside google cloud) as a cloud function;</div><div><br /></div><div><span></span><blockquote><span> </span> gcloud run deploy --image gcr.io/PROJECT-ID/helloworld --platform managed</blockquote><span class="pln" style="box-sizing: inherit; color: #37474f; font-family: "Roboto Mono", monospace; font-size: 14px;"></span></div>You will then be asked in which region of the world you would like to deploy the cloud function , and after deployment you will see which url you can use to access the cloud functions, something like;<div><br /></div><div><blockquote>https://helloworld-eszmdol7vq-lz.a.run.app/</blockquote></div><div><br /></div><div>Which will then return the default Zinc web-server homepage</div><div><br /></div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2maXUNnOYBvgoENsaMezVLdW6Brd9UTqyvWsP99QbSFBlnDdaBN_x8AADPG7Qzr23Ux0Ztkodmwb5oB9ifgOzHL8EWX88RvxIAq-QD-x8_EzPYnWkfQvYDZmWKlIr0NyoBJ7QdTOTnmBN//" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="378" data-original-width="774" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2maXUNnOYBvgoENsaMezVLdW6Brd9UTqyvWsP99QbSFBlnDdaBN_x8AADPG7Qzr23Ux0Ztkodmwb5oB9ifgOzHL8EWX88RvxIAq-QD-x8_EzPYnWkfQvYDZmWKlIr0NyoBJ7QdTOTnmBN//" width="320" /></a></div><br />Now, if you go to the google cloud web console, you can also verify that the cloud function is deployed, as well as see some statistics;</div><div><br /></div><div></div><blockquote><div>https://console.cloud.google.com/run?project=PROJECT-ID</div><div></div></blockquote><div><br /></div><div><br /><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRavtRWAU2NhfjEPFhVBnN-6rOQO-iKCSvHW9dguxBA8yczJRDQtX9ExSTov8EkmBf23zs-DRw-ExAnWKclp26Z4V2eR8VpflLHou72VMugnB9F2BZ9YqLB1fojRrhd6KU4_6jYnP_SIcM//" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="427" data-original-width="1172" height="117" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRavtRWAU2NhfjEPFhVBnN-6rOQO-iKCSvHW9dguxBA8yczJRDQtX9ExSTov8EkmBf23zs-DRw-ExAnWKclp26Z4V2eR8VpflLHou72VMugnB9F2BZ9YqLB1fojRrhd6KU4_6jYnP_SIcM//" width="320" /></a></div><br /><br /></div><div>There you go, please leave comments or questions, if you spot any bugs or if there is something you want me to expand on. I'm also mostly on the Pharo discord server; https://pharo.org/community</div><div><br /></div><div><br /></div><div><br /></div></div></div>Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-13773821240507805752020-03-23T14:07:00.000-07:002020-03-24T02:47:30.678-07:00A Cloud SDK for Pharo Smalltalk<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLRSGpi_sn-rbvfK9YY9M_0zxiA_mOxpwfcYSjevxD50KyMIVrEO18hOUU5vaEKMbIE-M9EH2r_oNGtAR1GAEmiI82Reli_4ru7B5ThzInM0XP-qpVk_LDU4VGHzDakPN1mI7XiHsfVDy5/s1600/Screenshot+at+2020-03-23+11-51-41.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="814" data-original-width="1157" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLRSGpi_sn-rbvfK9YY9M_0zxiA_mOxpwfcYSjevxD50KyMIVrEO18hOUU5vaEKMbIE-M9EH2r_oNGtAR1GAEmiI82Reli_4ru7B5ThzInM0XP-qpVk_LDU4VGHzDakPN1mI7XiHsfVDy5/s400/Screenshot+at+2020-03-23+11-51-41.png" width="400" /></a></div>
<br />
<br />
So I accidentally made a Cloud SDK.<br />
I was actually trying to make a game from the beginning, and as part of that I wanted the game to have a global high-score list.<br />
<br />
But that meant I needed to have some way for players (if they choose to) to authenticate themselves, so that the list at least have the right name for a score. So some kind of server-side logic was needed.<br />
<br />
I was using <a href="https://pharo.org/">Pharo 8</a> to create the game, and it felt like a good idea to write the server parts in Pharo as well. The normal way to deploy a server-side application to a cloud provider is to first make a Docker container for it. There are a couple of good instruction <a href="http://wiki.astares.com/pharo/613">here</a> and <a href="http://wiki.astares.com/pharo/615">here</a>, for Pharo.<br />
<br />
But building Docker images normally means that I would need to use a shell and run some commands, manipulating files and uploading them using custom CLI commands for the given cloud provider. It didn't feel very Smalltalk-y. I'd rather stay inside the Image and do everything without having to juggle files and additional software installations and all that.<br />
<br />
It was a bit tricky, but it worked. The result is this project; <a href="https://github.com/psvensson/cloudsdk-st">https://github.com/psvensson/cloudsdk-st</a> which contains an application to (hopefully) make the process more streamlined. It is an alpha release, and have the following constraints;<br />
<br />
1. It only works for Google Cloud (at the moment)<br />
2. It can only deploy Pharo Smalltalk applications to <a href="https://cloud.google.com/run">Google Cloud Run </a>(fully managed cloud functions).<br />
<br />
The workflow is as follows;<br />
<h3>
Add a key for a Google Cloud service account.</h3>
If you already have a google account (gmail, you know), you can access and enable Google Cloud by going to the console here; <a href="https://console.cloud.google.com/">https://console.cloud.google.com/</a><br />
<br />
A service account is an identity that can access certain parts (or everything) of your Google Cloud account on behalf of you. This is in essence what the application needs to do - to impersonate you and to send commands to your Google Cloud project as if it were you, to build and deploy Docker containers.<br />
<br />
You can find instructions on how to use service accounts and how to create and download private keys for them here; <a href="https://cloud.google.com/iam/docs/creating-managing-service-account-keys">https://cloud.google.com/iam/docs/creating-managing-service-account-keys</a> . I also have some instructions on this in the project README.<br />
<br />
This is what a downloaded service account JSON key looks like;<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsrFWTAlwupbCYLyWKRTBQkxyBZNJ-9XYyXD2NWOmOqzNUpb1AmcXc-CKM73-sTdEs_Hp_ZcAph_xlqgm-zTtXKF5ig8q736MpCcdbvrUalWj_dOIU8udaBZtGGMFBLwyN5H-r1A04Z4Lo/s1600/Screenshot+at+2020-03-23+21-19-13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="364" data-original-width="1139" height="203" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsrFWTAlwupbCYLyWKRTBQkxyBZNJ-9XYyXD2NWOmOqzNUpb1AmcXc-CKM73-sTdEs_Hp_ZcAph_xlqgm-zTtXKF5ig8q736MpCcdbvrUalWj_dOIU8udaBZtGGMFBLwyN5H-r1A04Z4Lo/s640/Screenshot+at+2020-03-23+21-19-13.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
After having installed the cloudsdk-st project in your image, you start it by doing the following in a playground;<br />
<br />
CCMainWindow open<br />
<br />
And the first thing you need to do after that is to click 'New Account' which lets you either paste the text contents of the key into the application directly, or select a file containing the key.<br />
Here is an example where I have four different keys installed, where each key can connect to a different project of yours. It is not uncommon to create on project for 'staging' and another for 'deployment'.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWIJ8ySE7h43yzWBO-iSTMHtScHxdqqNJRdVz7-JNA3RNQZY3c2eHqJjwRHDSX7tHJciG088trN22vDEa_05Kya5gzK0ou83WFDndMImceTrTzvqJPuypcARF653bBcwpkSen3uIRSDLdA/s1600/Screenshot+at+2020-03-23+21-10-33.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="393" data-original-width="412" height="381" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWIJ8ySE7h43yzWBO-iSTMHtScHxdqqNJRdVz7-JNA3RNQZY3c2eHqJjwRHDSX7tHJciG088trN22vDEa_05Kya5gzK0ou83WFDndMImceTrTzvqJPuypcARF653bBcwpkSen3uIRSDLdA/s400/Screenshot+at+2020-03-23+21-10-33.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h3>
Create a Template</h3>
<br />
Now we need to decide what to deploy. The right part of the application contain a list of Application Templates. A template consists of three parts;<br />
<br />
1. An editable base Dockerfile, which you need not change if you're OK with running Pharo 7<br />
2. An editable load script, which is the Smalltalk code to be executed to start your service. For almost all purposes, you will have to have a (Zinc) web server listening on port 8080 and your own custom code to handle requests. This is also the default for the template from the beginning.<br />
3. A list of external dependencies. You can search for and add Smalltalk packages by clicking 'Add Dependency'<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSPAwnVGHZX-jbIxnyZh9l6GZsDjrpv3S1lZ50hfNwu-VBK1_rtnh3bN-sJ6nFW7sp5GgCFUftUUKvqCc-kXxuG5JKCBUVNMa0aHtZ99qTSoHVMsge8fbOxX60tC_eUt9JyYIl549PcffX/s1600/Screenshot+at+2020-03-23+21-29-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="609" data-original-width="674" height="361" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSPAwnVGHZX-jbIxnyZh9l6GZsDjrpv3S1lZ50hfNwu-VBK1_rtnh3bN-sJ6nFW7sp5GgCFUftUUKvqCc-kXxuG5JKCBUVNMa0aHtZ99qTSoHVMsge8fbOxX60tC_eUt9JyYIl549PcffX/s400/Screenshot+at+2020-03-23+21-29-11.png" width="400" /></a></div>
<br />
You can write some text to search for packages to add as dependencies and also select to search for only Pharo or Smalltalk tags (or none). Currently the search is only done on Github but Smalltalkhub support is planned in the near future.<br />
<br />
When the Template is used to create a container, the list of dependencies will be translated into Smalltalk code loading the dependencies using metacello, so the packages will be available to you loading script.<br />
<br />
To actually deploy this template to a Cloud Run cloud function you must first enable a couple of things in your project.<br />
<ul>
<li>Granting access for Google Cloud build to deploy to Google Cloud Run, by setting 'Cloud Run Admin' to enabled here; (<a href="https://console.cloud.google.com/cloud-build/settings">https://console.cloud.google.com/cloud-build/settings</a>).</li>
<li>Enabling the Cloud resource manager API, here; (<a href="https://console.developers.google.com/apis/api/cloudresourcemanager.googleapis.com/overview">https://console.developers.google.com/apis/api/cloudresourcemanager.googleapis.com/overview</a>)</li>
<li>Enabling the Cloud Run API, here; (<a href="https://console.developers.google.com/apis/api/run.googleapis.com/overview">https://console.developers.google.com/apis/api/run.googleapis.com/overview</a>)</li>
</ul>
<h3>
Creating and deploying container</h3>
After that you can click 'Create Container' (which in retrospect should really be called deploy, I now realize :) ), which will do the following;<br />
<br />
1. Package the Dockerfile and load file strings as 'files' inside an in-memory zip archive<br />
2. Send the zip file to the Google Cloud Build system<br />
3. Telling the Cloud Build system to create a Docker container of the contents of the file<br />
4. Deploy the newly created Docker container to a Cloud Run function with the same name.<br />
<br />
This process takes 1 - 2 minutes normally.<br />
<br />
You can watch the build taking place by going here after you have started it; <a href="https://console.cloud.google.com/cloud-build/builds">https://console.cloud.google.com/cloud-build/builds</a><br />
<br />
When (and if) everything is done, you will have a new Cloud Run cloud function popping up here; <a href="https://console.cloud.google.com/run">https://console.cloud.google.com/run</a><br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdbYdwR7T9CzEfn1XtrJ5lHBTyq72t8JeEKQFSwrMQ6Su4L3x3UUhtxKi6lOumf2y4Oyf5k5vgAdBiFkKlwEDs2t57lgawphP3I5Xk-IEdWthDAqW5HQqxAyKZqSWGOT3zpbYGGcvlBzvf/s1600/Screenshot+at+2020-03-23+21-45-52.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="510" data-original-width="1527" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdbYdwR7T9CzEfn1XtrJ5lHBTyq72t8JeEKQFSwrMQ6Su4L3x3UUhtxKi6lOumf2y4Oyf5k5vgAdBiFkKlwEDs2t57lgawphP3I5Xk-IEdWthDAqW5HQqxAyKZqSWGOT3zpbYGGcvlBzvf/s640/Screenshot+at+2020-03-23+21-45-52.png" width="640" /></a></div>
<div>
You can also see the the results in the application. the 'Containers' button lists and give details about all Google Cloud Build containers that is build for your project.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHXoyKcOVwsdENKO_dRh93Z2y-pmAilyC-eNUAO98Oul_7I2I2ZDqD4PvRyzCrEM8gg0VyxBHom6N5ptdv6ermjNTVbZpY-q2Lb4pH08S_z3QM2l8igNVK3yTbArWnwvJ_0Cys3PIgSYqS/s1600/Screenshot+at+2020-03-23+21-47-51.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="495" data-original-width="576" height="342" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHXoyKcOVwsdENKO_dRh93Z2y-pmAilyC-eNUAO98Oul_7I2I2ZDqD4PvRyzCrEM8gg0VyxBHom6N5ptdv6ermjNTVbZpY-q2Lb4pH08S_z3QM2l8igNVK3yTbArWnwvJ_0Cys3PIgSYqS/s400/Screenshot+at+2020-03-23+21-47-51.png" width="400" /></a></div>
<div>
<br /></div>
<div>
The 'Build results' button lists and gives details of the build process(es);</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE_IVoxsEN93Jh5maWG3htu4T8t9CESUZ7_DzYGLQ-ZqQoqv6qc1sNfBTgKK3JioY-u_fAOHZ0KXn7S7bU0vzQU3um7Kf6WxU_j0omSSzQIIpoeFeiMrw9qad7XaWr9VoZdxJz0FPyYQdP/s1600/Screenshot+at+2020-03-23+21-51-04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="484" data-original-width="574" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE_IVoxsEN93Jh5maWG3htu4T8t9CESUZ7_DzYGLQ-ZqQoqv6qc1sNfBTgKK3JioY-u_fAOHZ0KXn7S7bU0vzQU3um7Kf6WxU_j0omSSzQIIpoeFeiMrw9qad7XaWr9VoZdxJz0FPyYQdP/s400/Screenshot+at+2020-03-23+21-51-04.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Finally the 'Deployments' button shows active and running Cloud Run cloud functions.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEbKC6tSqar25_HWjxaSCQl3DwsROhBY7WstgVro8nV6kNz6vmg4vbha61absVdVv3dC2zKLb_5VS43nASHqAj0-abNwzAAprr4RNFpWNMvhM2Cr1-GSdpb4KPCx2LzMghH4MXcQp5DeYq/s1600/Screenshot+at+2020-03-23+21-52-08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="492" data-original-width="579" height="338" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEbKC6tSqar25_HWjxaSCQl3DwsROhBY7WstgVro8nV6kNz6vmg4vbha61absVdVv3dC2zKLb_5VS43nASHqAj0-abNwzAAprr4RNFpWNMvhM2Cr1-GSdpb4KPCx2LzMghH4MXcQp5DeYq/s400/Screenshot+at+2020-03-23+21-52-08.png" width="400" /></a></div>
<div>
<br /></div>
<div>
But 'running' is a bit of a misnomer actually, as cloud functions only runs when called. If not called for a while, the container spins down, so you only pay for the times the function is actually accessed. But mostly it is free as the first 2 million calls are free for every month, so it is a comfortable way to start testing while also being live in the clouds, so to speak.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
And the game? It looks a bit like this and I hope to blog about it sometime soon as well, when I've rested a bit. It's currently a true rogue-like (as in; like rogue, actually, not just anything random with permadeath slapped on). I will have to make it real-time, rather than runt-based, in the spirit of <a href="https://mangband.org/docs/screenshots">mangband</a> to accommodate multi-user adventures, though</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRIjJNdw-sl_CRFBgR3nZwlVcB6Yxx3LuV11lNNGwI8-jpAvV0YZdd5qB0qEMPyBk8JxN7XQXkVC21P0LrHsehpfI06T4Btc9j2KpxShc5ZV2zFN0NNzYpO2wWB6ADB6jf4UXR2hQnq4C_/s1600/Screenshot+at+2020-01-21+20-24-18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="583" data-original-width="1036" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRIjJNdw-sl_CRFBgR3nZwlVcB6Yxx3LuV11lNNGwI8-jpAvV0YZdd5qB0qEMPyBk8JxN7XQXkVC21P0LrHsehpfI06T4Btc9j2KpxShc5ZV2zFN0NNzYpO2wWB6ADB6jf4UXR2hQnq4C_/s640/Screenshot+at+2020-01-21+20-24-18.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<br />Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-82964911313307242272019-12-22T07:16:00.000-08:002019-12-25T23:25:54.217-08:00What's so special about Smalltalk anyway?<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTv8XUxu0QLY4PtrJQ9RirBfulBjbv1TGKbl4J-2Cjog6-YW-eOq1iETMgDwHiDSf55QS61jT43RaKs40aDQSW5FfeB3SM9BolWzbscCpMD8SWq6t4H0z91ZbjwJrcVX87JT2d8RqyY-D/s1600/DDC85fxU0AQlVCY.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1091" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTv8XUxu0QLY4PtrJQ9RirBfulBjbv1TGKbl4J-2Cjog6-YW-eOq1iETMgDwHiDSf55QS61jT43RaKs40aDQSW5FfeB3SM9BolWzbscCpMD8SWq6t4H0z91ZbjwJrcVX87JT2d8RqyY-D/s320/DDC85fxU0AQlVCY.jpg" width="289" /></a></div>
<br />
Maybe you've seen someone mention Smalltalk, perhaps not knowing what it is, or if you do, wondering why there would be a reason to even bring up such an old, most probably dead programming language at all.<br />
<br />
You might know that Smalltalk was invented in the 70s at Xerox PARC, that it was arguably the first implementation of <a href="https://hackernoon.com/back-to-the-future-with-smalltalk-57c68fab583a">modern OO</a> as we know it, that <a href="https://en.wikipedia.org/wiki/SUnit">Unit testing</a> and modern <a href="https://en.wikipedia.org/wiki/Just-in-time_compilation">JIT compilation</a> was first implemented in Smalltalk and perhaps a number of other historical tidbits.<br />
<br />
And the language itself has inspired many other programming languages, Ruby, Python, Objective-C, <a href="https://en.wikipedia.org/wiki/Common_Lisp_Object_System">CLOS</a>, and even Java. So if you're already developing in one of those languages, you're already benefiting from all that knowledge, so no need to spend any of you attention on computer history, right?<br />
<br />
But what is missing from that narrative is how Smalltalk programming is actually done, rather than the language specification as compared to any other programming language. The secret sauce, as it were.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://cdn.shopify.com/s/files/1/0188/0032/products/hot-ones-fiery-chipotle-sauce-pepper-ghost-habanero-heat-level-05-chilly-chiles-largest-selection-of-in-canada-liquid-flavor_673_900x.jpg?v=1553133447" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="600" height="200" src="https://cdn.shopify.com/s/files/1/0188/0032/products/hot-ones-fiery-chipotle-sauce-pepper-ghost-habanero-heat-level-05-chilly-chiles-largest-selection-of-in-canada-liquid-flavor_673_900x.jpg?v=1553133447" width="150" /></a></div>
<br />
<br />
Most programming languages today are source-code based. It is so obvious so you might now be thinking what the alternative could be. I mean obviously, you're writing source code in a file, right? That is how things are done.<br />
<br />
It turns out programming can be done in another, mostly quite weird way, with huge but non-obvious immediate benefits. I will now try to describe how this other strange way of programming is done in practice.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://upload.wikimedia.org/wikipedia/commons/6/6b/Pharo_6.0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="581" data-original-width="800" height="232" src="https://upload.wikimedia.org/wikipedia/commons/6/6b/Pharo_6.0.jpg" width="320" /></a></div>
<br />
<br />
With <a href="https://www.gnu.org/software/smalltalk/manual/gst.html">few exceptions</a>, Smalltalk implementations are combinations of programming language, IDE, debugger and run-time, all wrapped up into one (although it can run head-less when it needs to).<br />
<br />
Smalltalks are image-based systems, meaning that everything that happens is in-memory, which can be serialized to a changes file, which is reloaded when the VM is restarted.<br />
<br />
That means that all classes and methods created and all changes made are made only within that image. When you make changes to a method, it is compiled and linked immediately into the image.<br />
<br />
All changes are live.<br />
<br />
This means that your program is running inside the image, and any changes you make to the classes and methods that makes up your code, will immediately affect the program as it runs.<br />
<br />
Here is an example; I'm making a small <a href="https://github.com/psvensson/golgotterath">rogue-like isometric game</a> in a Smalltalk called<a href="https://pharo.org/"> 'Pharo'</a>. The game is running as I'm editing it and adding features.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSA-iR9JowYQ-kZJrB9bXmomfbN8gEOEwyVasJ0VpZ1bQ_rjlpC4cH4HJ0Rbnwa8ViZcW-X-56LgNGZfHFbrvwebe6wlO0t2eQsQuWpYWaR23m5AGU3OFfOmeFLbORxWBKIPVGnBwZDt7b/s1600/Screenshot+at+2019-12-22+16-21-10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1092" data-original-width="1600" height="435" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSA-iR9JowYQ-kZJrB9bXmomfbN8gEOEwyVasJ0VpZ1bQ_rjlpC4cH4HJ0Rbnwa8ViZcW-X-56LgNGZfHFbrvwebe6wlO0t2eQsQuWpYWaR23m5AGU3OFfOmeFLbORxWBKIPVGnBwZDt7b/s640/Screenshot+at+2019-12-22+16-21-10.png" width="640" /></a></div>
<br />
If an error occurs, which happens when you are halfway into implementing something, the debugger shows what is missing and have the same kind of code editor there. When you fix the problem and save the method, you can continue running your code with the new changes. There might be new errors, handled in the same way, until finally everything works again.<br />
<br />
What do you need to do to make those changes permanent? Nothing, you just did it. This is sometimes referred to as 'debugger-based development' :) .<br />
<br />
This is a big thing, even if it might just seems quirky right now. This mode of developing means that there is a very tight loop between coding, running, discovering problems and fixing them. There is no focus on anything else except the code.<br />
<br />
Consider also for a moment what was not present in the example above;<br />
<ul>
<li>Saving to a file</li>
<li>Compiling the file to an intermediate format</li>
<li>Running the code and switching to another window to see it run</li>
<li>Reading a long text-based error message</li>
<li>Switching back-and-forth between your source-code editor (doing some simulations of the target environment but not quite there) and the error message</li>
</ul>
In conversations I've had with engineering directors of companies such as LabView, I've heard estimates that they save at least 5% development time (a conservative figure, which I personally estimate to be higher) just by using Smalltalk. And that the reason for this is just this tight loop.<br />
<br />
This does seem nice, I guess, but seriously, how do you even develop like this? How do team members share code? How do you even deploy anything? Can it run int the cloud, on mobile, what?<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://i.imgur.com/G1F1ECN.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="731" height="200" src="https://i.imgur.com/G1F1ECN.jpg" width="182" /></a></div>
OKOK, easy. Right. As it turns out, Smalltalk has evolved quite a bit in the last decade to have the following features;<br />
<br />
<a href="https://github.com/pharo-vcs/iceberg/wiki/Tutorial">Full git integration</a> (github/lab/whatnot), persisting code changes as files, but pulling just means some new classes pop up and some methods have changed. Yes, there full git support for diffing, merging, branching, et.c. It's just done from a package and class perspective instead of having to play file management.<br />
<br />
<a href="http://wiki.astares.com/pharo/613">Works with Docke</a>r, with a number of ready-to-go images to derive from, or to use. Image sizes range from 71MB to 200MB.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://img.pngio.com/free-download-engineer-logo-png-docker-logo-png-260_260.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="260" data-original-width="260" height="200" src="https://img.pngio.com/free-download-engineer-logo-png-docker-logo-png-260_260.jpg" width="200" /></a></div>
<br />
This means, incidentally, that you can now easily run a Smalltalk app both inside a Kubernetes cluster, scaling it like nobody's business, or as an AWS Lambda or Google/Azure Cloud Function. There are even a a couple of packages for integrating more fully with <a href="https://github.com/newapplesho/aws-sdk-smalltalk/wiki">AWS services</a>.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhklUQ-NPhlVJjRdx3F8kIVTsVlHORRH47f_OVbUFTVlFu5Zd9hdTzuz98jUJ3jMFgwhV7-S3g8jaxNBtGFwd6fr1uaumd5SqSZ2FWWbw8fAz9VOQtUeuiSjkymaHt60juQjtwQgynkm0nh/s1600/Google-Cloud-Logo-180pxX180px.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="180" data-original-width="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhklUQ-NPhlVJjRdx3F8kIVTsVlHORRH47f_OVbUFTVlFu5Zd9hdTzuz98jUJ3jMFgwhV7-S3g8jaxNBtGFwd6fr1uaumd5SqSZ2FWWbw8fAz9VOQtUeuiSjkymaHt60juQjtwQgynkm0nh/s1600/Google-Cloud-Logo-180pxX180px.png" /></a></div>
As for deploying desktop apps, it is possible to ship a platform-specific Smalltalk VM, a trimmed image and have a script run it with editing/editor disabled. Not perfect but works well, apparently.<br />
<br />
Mobile is lagging a bit, but with three interesting projects coming up strong the last years; One is <a href="https://pharojs.github.io/mobileAppDev.html">PharoJS</a>, which is a Smalltalk-to-JS compiler which leverages Cordova (running JS in a webview) and <a href="https://www.slideshare.net/esug/scarlet-smalltalk">Scarlett Smalltalk</a> which is on the first steps of becoming a kind of Smalltalk Flutter, with native bindings for both iOS and Android.<br />
<br />
Finally <a href="https://lolg.it/amber/amber">Amber Smalltalk</a> is a Smalltalk implementation in JavaScript, running in the browser, letting you live code your web app, and <a href="https://medium.com/smalltalk-talk/amber-alert-we-can-do-mobile-apps-34b2d4d32731">which also can make mobile apps,</a> suing the same trick (but posibly earlier) that PharoJS did.<br />
<br />
<br />
I hope I didn't steal too much of your time and also that I conveyed a bit of why Smalltalk can help and perhaps even make something possible that have previously seemed too hard to do. There are other interesting features that the editor and debugger has which I hope to give detailed post about soon.<br />
<br />
<br />
<br />Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-25122974588218547442016-09-22T11:24:00.002-07:002017-08-12T01:20:37.108-07:00A modest proposal on solving the problem with developer latin<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Latin is considered a dead language, as it has no native speakers any more. Whether this is true or not depends on your definition since it is indeed learned and spoken all over the world by a minority of speakers, mostly for use in esoteric rituals or for academic studies.<br />
<br />
In either case, Latin is incidental at best to gauging the proficiency of (say) an English-speaker of today. However, Latin is really clearly defined with lots of interesting grammar and is probably kind of a cool language to ask questions about and to see how well English-speakers are able to articulate themselves in it.<br />
<br />
Also, some English words and syntax derives directly from Latin and that can be quite interesting to follow in itself.<br />
<br />
But if you were to hire a journalist, a tech writer or perhaps a person working a lot with written communication in general, how useful would a throughout test on Latin be? Not very? I thought so.<br />
<br />
So, what has this to do with developers?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMs1dcmgyiq7uyixp0tqdI08RI1ucdbSqu9dmS5WtZTfMWpSBkHDTKXBuTrzF7tlO6oFTO8AImJBwmExleRC0FFlHy6y8DTsmB1i5kzz_r1q5pUFWW-kkV_MvyySLewhCnk9DlO4WMRoP6/s1600/_STAR1.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMs1dcmgyiq7uyixp0tqdI08RI1ucdbSqu9dmS5WtZTfMWpSBkHDTKXBuTrzF7tlO6oFTO8AImJBwmExleRC0FFlHy6y8DTsmB1i5kzz_r1q5pUFWW-kkV_MvyySLewhCnk9DlO4WMRoP6/s320/_STAR1.GIF" width="290" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Every two or three years I forget past experiences and think how nice it would be to work at, for example, Google, where I know lots of people and which seems to be an OK place to work. This often coincides with the re-evaluation of going it all alone in my own company and sometimes not having the kind of traction I'd like with what I do.<br />
<br />
And I realize this is a flogging a dead horse which has seen quite a lot of action throughout the years, but the main gist of all this is that I realized, mid through an interview, that the technical details we were discussion were very similar to Latin knowledge for an English-speaker.<br />
<br />
Even worse, I have it from the horses mouth (the very same) that in actual practice, there an awfully little Latin being spoken inside Google after you've been hired.<br />
<br />
Ho often do you re-balance a red-black tree? How often do you map a tree according to certain criteria onto an array? It sounds like you might, at some point. I guess. I'm using a lot of priority queues and trees when coding, but implementing them myself? Has never happened. Or, I did make my own quad-tree once. tbh.<br />
<br />
So how hard can it be? These are super-easy programming problems from university, after all. If you don't know them, what do you know? Right?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyiMN4RGJhUXyeasKetz-xf1SxN8-nd1Aat9XsCScnTH3WkdNiIvPTaH5NvVsKi7v3q48-z5G5PNcF2Ig78FHmCfSYhKcEmnP-h3t27oauLL5A-QqGGjIFErQVgjmVO7rDFkPuM9o3r4NP/s1600/E6Sd4GC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyiMN4RGJhUXyeasKetz-xf1SxN8-nd1Aat9XsCScnTH3WkdNiIvPTaH5NvVsKi7v3q48-z5G5PNcF2Ig78FHmCfSYhKcEmnP-h3t27oauLL5A-QqGGjIFErQVgjmVO7rDFkPuM9o3r4NP/s320/E6Sd4GC.png" width="320" /></a></div>
<br />
Do you remember learning that new library or framework recently? The one where you sort of understood what it did but still made lots of silly mistakes the first week. And you, who have been coding for more than ten years (or 20 or 40, you get it). Isn't that embarrassing?<br />
<br />
It turns out that never mind how experienced you are or how smart you are, unless you are experienced in the specific area in question, you're not so hot anymore. You don't get that extra days or week or whatever.<br />
<br />
That's all fair, but to train specifics of implementing certain classical algorithms and edge-cases thereof that will never ever at all be used in production is indeed a bit like asking for knowledge of Latin for a position where a thorough, current knowledge of (say) English is required.<br />
<br />
And of course you can spend those extra days and weeks and read all those websites and books that train you what the current slew of Latin is hot, people do it all the time.<br />
<br />
But - and here comes the modest proposal btw - wouldn't it be a better approach to actually test people on the skills they are supposed to use at the position they are supposed to be hired for?<br />
<br />
As a company you are certain to hire people who are smart - smart enough to read up on a number of very odd and old, basic algorithms, learn their edge-cases and actual talk fairly fluently about it all at the end of the interview. So you're sure to get both unnecessarily motivated and very smart people to hire.<br />
<br />
That's great!<br />
<br />
And you won't get the people who quite frankly are tired of all that Latin.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXBCzC8_By6fDcvaX9RtaVmPVWriPro7P1f7682fYjpi97evfpAN1LLMby-ASQrMjXLHv43p70x67yOSVvybFcEihZhWKzmDWRw14Zf0cKUVZMN-ejfFO969h2kOFikXONi9qqu68zMgI0/s1600/kripT9I.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXBCzC8_By6fDcvaX9RtaVmPVWriPro7P1f7682fYjpi97evfpAN1LLMby-ASQrMjXLHv43p70x67yOSVvybFcEihZhWKzmDWRw14Zf0cKUVZMN-ejfFO969h2kOFikXONi9qqu68zMgI0/s320/kripT9I.jpg" width="271" /></a></div>
<br />
<br />
How about this;<br />
<br />
- You already know the devs you've sourced and filtered out are the top 5% or so<br />
- You know what they've been working on, which companies and github projects and so on<br />
- Go over one of their projects one-on-one<br />
- Ask them how they feel about testing<br />
- Ask them the worst bug or problem they've been responsible for<br />
- Ask them to write something on their own machine, on their IDE of choice, that is applicable to the position they're hiring for.<br />
<br />
Eh?<br />
<br />
You already know very well what you've got to lose, because you're losing it every day, by the tonnes. First company to go non-bonkers wins. :)<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-38094168066214822552015-12-28T10:40:00.001-08:002015-12-28T10:56:14.038-08:00Getting started with visual programming using Evothings Studio<h3>
Intro</h3>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjXCfZYxTKnfCNbe9SYnwtlX997VyNRLNlWkkCYDGLcP6rIaDZvnd0zbJldMCvelwoFY6i0rlvLlD_SMBqUjYuVuTuod-jndSqndPTIlmls38pXfBzPpoJG9R7V9dSfROsqkYWH7lu8_Ro/s1600/tumblr_nkrmvtmozg1qkjuqlo2_r1_1280.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjXCfZYxTKnfCNbe9SYnwtlX997VyNRLNlWkkCYDGLcP6rIaDZvnd0zbJldMCvelwoFY6i0rlvLlD_SMBqUjYuVuTuod-jndSqndPTIlmls38pXfBzPpoJG9R7V9dSfROsqkYWH7lu8_Ro/s320/tumblr_nkrmvtmozg1qkjuqlo2_r1_1280.gif" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
Last post I described how <a href="http://unclescript.blogspot.se/2015/12/all-tomorrows-lines-of-code.html">this crazy idea came about</a>, but I realized that I really needed to write a short introduction, for two reasons;<br />
<div>
<br /></div>
<div>
<b>1</b>. The Evothings node-red front-end parser works a little differently than the usual node-red run-time.</div>
<div>
<b>2</b>. It's not really clear where to go next when you've downloaded and started the node-red version of <a href="https://evothings.com/">Evothings</a> Studio.</div>
<div>
<br /></div>
<h3>
But why?</h3>
<div>
<br /></div>
<div>
Yes, why would you anyway? My hope is that many people would welcome an even easier route to getting started doing IoT apps. <a href="https://evothings.com/download/">Evothings studio </a>is the quickest route that I know of at the moment, given that you don't mind doing cross-platform JavaScript development and baking your app with cordova at the end.</div>
<div>
<br /></div>
<div>
Still, Evothings Studio is all about JavaScript, and if it's not your first programming language, there can be a lot of sharp corners to cut yourself on. </div>
<div>
<br /></div>
<div>
By packaging access to some of the Cordova and JavaScript BLE APIs as visually composable modules (in the node-red editor), I hope that it becomes even easier to create and experiment with apps the communicate with sensors or other Bluetooth devices.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizDpYdfaHhobNe7Em_a4i4H08fOZ6Ls9UFGPAq1hu5nD7Yqho2f2RPYwMEInx3EnNRYpIJryfeW_8rAxHajQCnIunUldzlmv44mhB7n_h7UKutMcbTq5EupauMnuxVLThojT_wZXuQhIxZ/s1600/oR9PXz7.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizDpYdfaHhobNe7Em_a4i4H08fOZ6Ls9UFGPAq1hu5nD7Yqho2f2RPYwMEInx3EnNRYpIJryfeW_8rAxHajQCnIunUldzlmv44mhB7n_h7UKutMcbTq5EupauMnuxVLThojT_wZXuQhIxZ/s320/oR9PXz7.jpg" width="255" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Prerequisites</h3>
<div>
<b>1</b>. Download the Node-red branch build of Evothings Studio here;</div>
<div>
<br /></div>
<div>
Windows: <a href="https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Win_32_2.0.0beta2-node-red.zip">https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Win_32_2.0.0beta2-node-red.zip</a></div>
<div>
<br /></div>
<div>
OSX: <a href="https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Mac_64_2.0.0beta2-node-red.zip">https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Mac_64_2.0.0beta2-node-red.zip</a></div>
<div>
<br /></div>
<div>
Linux (Yay): <a href="https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Linux_64_2.0.0beta2-node-red.zip">https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Linux_64_2.0.0beta2-node-red.zip</a></div>
<div>
<br /></div>
<div>
<b>2.</b> Unpack it in your home directory (*NOT* under C:\program files or the like, if you're running Windows)</div>
<div>
<br /></div>
<div>
<b>3</b>. Make sure it runs, and looks reasonably like this:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSERnnYM0g0xC70IuPZFHzYLRHtVLYFhLhc0xaWXe-4itLMrgUG8txSbYRUUVerVAyk7gNE8rKcJ0QBcdXClTS5jh9FZIQbvVVEY9dc0Ma1uFCVR6ppG7NPLzMB1IlBY6WOrsE16AKZNl6/s1600/Screenshot-46.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="304" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSERnnYM0g0xC70IuPZFHzYLRHtVLYFhLhc0xaWXe-4itLMrgUG8txSbYRUUVerVAyk7gNE8rKcJ0QBcdXClTS5jh9FZIQbvVVEY9dc0Ma1uFCVR6ppG7NPLzMB1IlBY6WOrsE16AKZNl6/s320/Screenshot-46.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
What you're running now is essentially the latest beta of Evothings Studio 2.0, but with a couple of modifications, so everything you'd like to do with the original studio (<a href="https://evothings.com/download/">and it's quite a lot</a>), you can do here as well. The modifications cooks down to a new button for each of the projects under 'My Apps' (any front-end project, really, that can be anywhere on your machine) that let you launch a node-red editor and create+edit a flows.json file in the directory where the index.html of your project resides.</div>
<div>
<br /></div>
<div>
<b>4.</b> Go to the Examples tab, and note the two projects 'Hello Node-Red World' and 'Node-Red Front-End TI Sensortag'.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Dpg9J7Yt_JeSvYrlUB494TKzjMwEaCdrVRk8elXsdR5mF46aLqRIs3gbbLydr7VeZAEbU4h0GHGlPoKdbutfA3TKZmhB9jI7Fn6lei8WT1rQ5eedpyMa_6jnvsTR6gjYO2Fv19rPKVzj/s1600/Screenshot-48.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Dpg9J7Yt_JeSvYrlUB494TKzjMwEaCdrVRk8elXsdR5mF46aLqRIs3gbbLydr7VeZAEbU4h0GHGlPoKdbutfA3TKZmhB9jI7Fn6lei8WT1rQ5eedpyMa_6jnvsTR6gjYO2Fv19rPKVzj/s320/Screenshot-48.png" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
The two examples are the only ones that you can actually use directly, if you want to see how the node-red editor works together with the studio to push out incremental changes to your mobile.</div>
<div>
<br /></div>
<div>
<b>5.</b> Speaking of which, it's time to install the viewer on your phone. Here's the link for <a href="https://itunes.apple.com/se/app/evothings-viewer/id1029452707?mt=8">iOS</a> and <a href="https://play.google.com/store/apps/details?id=com.evothings.evothingsviewer&hl=sv">Android</a>, and make sure it runs and looks like the image below;<br />
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge_Fa9Gil3X_Ccwyc5dYDXNEdRVicsbBdvLjU_76yzbmjynple0QVlx448UJeUA2D6MQkkpq1dgmcEwGaENPm1bRBqlaWIxsVj2_a-PXmcDFa24IaFJzvY-UPLf6qLQo6_HeEybDaD8PNG/s1600/Screenshot_20151228-183907.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge_Fa9Gil3X_Ccwyc5dYDXNEdRVicsbBdvLjU_76yzbmjynple0QVlx448UJeUA2D6MQkkpq1dgmcEwGaENPm1bRBqlaWIxsVj2_a-PXmcDFa24IaFJzvY-UPLf6qLQo6_HeEybDaD8PNG/s320/Screenshot_20151228-183907.png" width="180" /></a></div>
<div>
<br />
<br />
<br /></div>
<div>
<b>6</b>. To connect your phone and the studio, you generate a one-time key in the studio and enter it on the phone.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRsHXJGgtrXUQZ8nJfzCXtnX2PaKZoZjOYrt-lE-jcsxp33PXur8uSeeFI5tLUUd02ZHXv_b4oJshvH9JkUZ3iHBcFAbWu0iG3hij75NRDtbKPhkEcVVH4Oc6ri-joPOZ4rQ4hS_I2uJjY/s1600/Screenshot-49.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="304" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRsHXJGgtrXUQZ8nJfzCXtnX2PaKZoZjOYrt-lE-jcsxp33PXur8uSeeFI5tLUUd02ZHXv_b4oJshvH9JkUZ3iHBcFAbWu0iG3hij75NRDtbKPhkEcVVH4Oc6ri-joPOZ4rQ4hS_I2uJjY/s320/Screenshot-49.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJxEoiA-GF3XdbtsnvKQdQvEV1FvmeVq1PLfQmYpVuYz5veqNO-o73hZp8stoju5828NPLO-s7xvOxHOcWg_Twfua5-F0Y0C6GyQKk1wQztHgCNFxmHY9uQQUfZwUwvr0Ck6UTDmrTURN3/s1600/Screenshot_20151228-184418.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJxEoiA-GF3XdbtsnvKQdQvEV1FvmeVq1PLfQmYpVuYz5veqNO-o73hZp8stoju5828NPLO-s7xvOxHOcWg_Twfua5-F0Y0C6GyQKk1wQztHgCNFxmHY9uQQUfZwUwvr0Ck6UTDmrTURN3/s320/Screenshot_20151228-184418.png" width="180" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b>7.</b> Now, you should have one client connected at the lower right status field of the studio. You re now ready to rock! If you want to avoid entering a new code every time you have crappy connectivity, you can log in (using github, google or plain email) to the proxy to make it preserve the session.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS_JehzXSPFHrsjHNfWrZEAdFq4xbdI9hWX6zhMN0fQrO9wpDlsFeipxcQne_dq5SYKTc7DrpRA0RQB4cOGL_L5fZYNDP0JbjuzZVEF1zuz2g0JEEoE63LspcnJGru8zpFoNEd1DMIGQm2/s1600/Screenshot-50.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS_JehzXSPFHrsjHNfWrZEAdFq4xbdI9hWX6zhMN0fQrO9wpDlsFeipxcQne_dq5SYKTc7DrpRA0RQB4cOGL_L5fZYNDP0JbjuzZVEF1zuz2g0JEEoE63LspcnJGru8zpFoNEd1DMIGQm2/s320/Screenshot-50.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<b>8.</b> Now copy the example project 'Hello Node-Red World' from the examples tab and by clicking the 'COPY' button next to it. When you are done, you're taken to the 'My Apps' tab where the new project will show up.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZljVpT11gSFILqJoaQcGM-iW_wNNz472O-2hL7XrLPjE40sXPXi-qJ7akmyQHze4iQrE-vHnnYRtOA5lRxLnyDBHlunNNw0XnfzhgMvDFZi9wCAae6lqCsX4vmWuK4uYMFIP9DpYksiTb/s1600/Screenshot-51.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZljVpT11gSFILqJoaQcGM-iW_wNNz472O-2hL7XrLPjE40sXPXi-qJ7akmyQHze4iQrE-vHnnYRtOA5lRxLnyDBHlunNNw0XnfzhgMvDFZi9wCAae6lqCsX4vmWuK4uYMFIP9DpYksiTb/s320/Screenshot-51.png" width="320" /></a></div>
<div>
<br /></div>
<div>
By clicking 'CODE' the studio open a system file browser that shows the root of the directory, to let you edit the files using your favorite editor. These files are a bit doctored to load and parse node-red flows.json files and to populate the mobile web page with the widgets that are defined there. You can of course edit the index.html and everything as you wish, and do both classical and node-red development at the same time (as long as you don't bork the node-red front-end stuff).</div>
<div>
<br /></div>
<div>
<b>9.</b> Click the 'RUN' button to push out your project to your mobile phone. It will (hopefully) like a bit like below when it lands;<br />
<br />
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM_8Pc-OX30ydabotgx7TQ_RIjwZ8BRt5nkNu9auF2yXKKQh6rYMFuGGyx8aDaSC0LMJXF-CGyYg29EPnQTI-_HUqxwP-O5oEtVuOzjKcUr8UJAoIU7buOdhTOHN4P5wZHqc5PGnXhabG-/s1600/Screenshot_20151228-185359.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM_8Pc-OX30ydabotgx7TQ_RIjwZ8BRt5nkNu9auF2yXKKQh6rYMFuGGyx8aDaSC0LMJXF-CGyYg29EPnQTI-_HUqxwP-O5oEtVuOzjKcUr8UJAoIU7buOdhTOHN4P5wZHqc5PGnXhabG-/s320/Screenshot_20151228-185359.png" width="180" /></a></div>
<div>
<br />
<br />
<br /></div>
<div>
<br /></div>
<div>
Not a beauty, by any means, but does contain a bare-bones examples of what a simple node-red front-end app could look like.</div>
<div>
<br /></div>
<div>
If you have any Bluetooth devices around, you can click 'SCAN' which lists all found (until you press the button (now saying 'STOP SCAN') again). Clicking on one of the found devices will list its services in a separate list.</div>
<div>
<br />
<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7WuMh1k1EjZ5U-nGA9MB44cQEYZfSqcCwZZm2IcWOHhARhN7KPlaVbIviFbuEuq7nXObsnbIbDqtSzG1WcMxGgottC-x-Lt6TGP4-S7I8djmw513sgxGLBdVaHHrSjdsv9yNoURrf16Gq/s1600/Screenshot_20151228-185702.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7WuMh1k1EjZ5U-nGA9MB44cQEYZfSqcCwZZm2IcWOHhARhN7KPlaVbIviFbuEuq7nXObsnbIbDqtSzG1WcMxGgottC-x-Lt6TGP4-S7I8djmw513sgxGLBdVaHHrSjdsv9yNoURrf16Gq/s320/Screenshot_20151228-185702.png" width="180" /></a></div>
<div>
<br />
<br /></div>
<div>
<br /></div>
<div>
OK, not very impressive.- Seen it before - yawn, right? But what I want to highlight here is not actually the functionality of the app but how it was made. </div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b>10.</b> If you go back to the 'My Apps' tab on the studio, now click the 'NODE-RED' button, which should bring up the visual node-red flows editor for the current project.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2LoLl7NjHPy231mwv4o7WZwjOgOJROhUc_ydou5vnAvEP8m4qsT2Vze5svS9iTi1xlEeakPqq7njquq1eUjg7m9EVLeJ9nPcO0uSnLvREGXtIufzzN91zOROjtARv2zRsW-FZCQ0yuTTA/s1600/Screenshot-52.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2LoLl7NjHPy231mwv4o7WZwjOgOJROhUc_ydou5vnAvEP8m4qsT2Vze5svS9iTi1xlEeakPqq7njquq1eUjg7m9EVLeJ9nPcO0uSnLvREGXtIufzzN91zOROjtARv2zRsW-FZCQ0yuTTA/s320/Screenshot-52.png" width="320" /></a></div>
<div>
<br /></div>
<div>
All node-red front-end apps must begin with a 'Page' module, which has connections to all other visible widgets under it, normally organized by 'Section' modules. Visible stuff like sections, buttons and so on are connected to each another sort of like a DOM tree, but after that, the connections between modules actually defines message-passing.</div>
<div>
<br /></div>
<div>
For example, the 'Scan' module is actually a Button module, which has been renamed to Scan. it will implement a Material Design Lite Button and when it is clicked, a message will be passed to whatever other module(s) it is connected to.</div>
<div>
<br /></div>
<div>
This button connect to two other modules - a function and a module called 'blescan'. Let's look at the function;</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHjNwh5Zh9ktgZJVezrlRZmH8-Tx2-rAOeNqmyN50ZMpBwA3-_5MbaYqxA6vNbTR7Tj3DF2hO5cmvbntHvEdITZQxEdiMjKz1fjDsBQ2JDW-ngHSWOPR4awe8Ma2lW6AqDryUTMe_QoKpc/s1600/Screenshot-53.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHjNwh5Zh9ktgZJVezrlRZmH8-Tx2-rAOeNqmyN50ZMpBwA3-_5MbaYqxA6vNbTR7Tj3DF2hO5cmvbntHvEdITZQxEdiMjKz1fjDsBQ2JDW-ngHSWOPR4awe8Ma2lW6AqDryUTMe_QoKpc/s320/Screenshot-53.png" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
All modules (including functions) gets passed one argument object called 'msg'. The convention is to have a property of msg called 'payload' which contain the important parts. </div>
<div>
<br /></div>
<div>
The payload passed by a button is the DOM event object of the click, which is then used to determine which new text caption the button should be set to. So buttons also can receive messages, and will change caption to that of the payload.</div>
<div>
<br /></div>
<div>
But the interesting thing with functions is that you can add them anywhere and use them to debug messages being passed. And now we come to a very nice thing with Evothings Studio itself - that you gets logs back from the running app on the phone, continually.</div>
<div>
<br /></div>
<div>
<b>11.</b> Click on the blue button named 'Tools' in the main Studio app window. you now get a new window with two parts - a small editor at the top (already populated with examples to try out) and at the bottom an area which display the logs from your app.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv-8UsqKQ3hkfmaP56k4ZbUkSInseK7wGvzt93yQ99uAUNn4_30fHBnSwwRv2q1i7Tw-m0k0aHfUwDlnwfQ2s-OsC1k4AX1KzUmdyGUw-g2GimD99y21db5Przx9Pgil8qCjerJhJK0VxF/s1600/Screenshot-55.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv-8UsqKQ3hkfmaP56k4ZbUkSInseK7wGvzt93yQ99uAUNn4_30fHBnSwwRv2q1i7Tw-m0k0aHfUwDlnwfQ2s-OsC1k4AX1KzUmdyGUw-g2GimD99y21db5Przx9Pgil8qCjerJhJK0VxF/s320/Screenshot-55.png" width="320" /></a></div>
<div>
<br /></div>
<div>
So if we add a log statement to the function, like this;</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQbl1H83j72cWa0dIf9_fcUXmYJj_PQtdr3zZ95UJfarRwyLL_-kySw4B0fhgpcv8uGRNTwBWxuFZJSILKAHHWD_HFcgiMTgMNusq8OnEoMYZ-ZlBmwAeKLWgR4HUB8P0OehsZf5SxzaJQ/s1600/Screenshot-57.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQbl1H83j72cWa0dIf9_fcUXmYJj_PQtdr3zZ95UJfarRwyLL_-kySw4B0fhgpcv8uGRNTwBWxuFZJSILKAHHWD_HFcgiMTgMNusq8OnEoMYZ-ZlBmwAeKLWgR4HUB8P0OehsZf5SxzaJQ/s320/Screenshot-57.png" width="320" /></a></div>
<div>
<br /></div>
<div>
It will result it some logs in the Tools window when the button is pressed.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzg9v_SBa7pYdF4SrrxDyZzusWxKzPvun6PXitxsaL6IpwClrHCeOrRQU8kTb6fOF1RMkJAJ80pgfRpoy4o0r54FWXS3qM_Q65WJbUS2EYneItMgIPAWFdjR9J2zRyZ83UNWIhwm26CUTY/s1600/Screenshot-58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzg9v_SBa7pYdF4SrrxDyZzusWxKzPvun6PXitxsaL6IpwClrHCeOrRQU8kTb6fOF1RMkJAJ80pgfRpoy4o0r54FWXS3qM_Q65WJbUS2EYneItMgIPAWFdjR9J2zRyZ83UNWIhwm26CUTY/s320/Screenshot-58.png" width="320" /></a></div>
<div>
<br /></div>
<div>
And, it turns out, quite a lot of my own silly happy-go-lucky developer logging while I'm making the nrfe-widgets. I should probably clean those up a bit. :) But what I wanted to show here is ..</div>
<div>
<br /></div>
<div>
<b>1.</b> You can develop apps visually in the node-red editor and still get quite a lot of functionality.</div>
<div>
<b>2</b>. The widgets will look sort of OK without *any* efforts at styling.</div>
<div>
<b>3</b>. The program that scan for BLE devices and then list the services of a selected one contained only three lines of code, over two functions (the other picked a property of the incoming message and sent it as output).</div>
<div>
<b>4</b>. <i>Three lines of code</i> that you write yourself, for a bespoke app, is a sweet small number to maintain.</div>
<div>
<br /></div>
<div>
The modules have documentation included in themselves, so when you select a module in the node-red editor, the documentation comes up in a sidebar to the right. This is a very nice way of doing things from the creators of node-red, and helps a lot when just getting started. I haven't documented very well, but I hope that it is enough to get started.</div>
<div>
<br /></div>
<div>
Again, please let me know what you'd like to see next and if you've managed to make anything yourselves using the editor!</div>
<div>
<br /></div>
<div>
Over and out, for now.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJb5KEzN8maPLUw2e83FBqOQZlT0e-Q5RwDet5S87BJ0Z2zow7uhX78WwQR5ud88KPl0kszzhHlUwQneSSMLvWEzn3RiPcp_sGo3yYsexeqlNHngl-GYviR-OYR5dcNtYNtgUH8qb3bRSo/s1600/zJPOApr.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJb5KEzN8maPLUw2e83FBqOQZlT0e-Q5RwDet5S87BJ0Z2zow7uhX78WwQR5ud88KPl0kszzhHlUwQneSSMLvWEzn3RiPcp_sGo3yYsexeqlNHngl-GYviR-OYR5dcNtYNtgUH8qb3bRSo/s320/zJPOApr.jpg" width="213" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com2tag:blogger.com,1999:blog-7919361321436933137.post-4917884348775297372015-12-25T06:12:00.000-08:002015-12-28T10:42:25.530-08:00All tomorrows lines of code<h2>
(That you don't have to write)</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPFFCbz5OetlKmBowiVRUI2UlKbm28KzunOh5yKSg0W1wmKHZeu7m9uWINphcNpmWHzcVZVRRBKMxLRQAWvlcv5EcXdyIS5vlfJsbVoB_rdnk2cZOgvn8s7KGY5iHo0HNqR4v5Bnal0vfr/s1600/Screenshot-12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPFFCbz5OetlKmBowiVRUI2UlKbm28KzunOh5yKSg0W1wmKHZeu7m9uWINphcNpmWHzcVZVRRBKMxLRQAWvlcv5EcXdyIS5vlfJsbVoB_rdnk2cZOgvn8s7KGY5iHo0HNqR4v5Bnal0vfr/s400/Screenshot-12.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVcdVDjKwfd1Sur9DEbvkiSmxOhm1xhvsLLQvW3MsDYxQHRZK_FZ4VDXG3EGtssSbCfeNs0SLCwxXiB44zifrQEUa2pEdnXJOG15F8z0-th3g5G0FgY-xhMy5wjE7grx-2xq3_GNKntZ2m/s1600/IMG_20151216_125115.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVcdVDjKwfd1Sur9DEbvkiSmxOhm1xhvsLLQvW3MsDYxQHRZK_FZ4VDXG3EGtssSbCfeNs0SLCwxXiB44zifrQEUa2pEdnXJOG15F8z0-th3g5G0FgY-xhMy5wjE7grx-2xq3_GNKntZ2m/s320/IMG_20151216_125115.jpg" width="320" /></a></div>
<div>
<br /></div>
<h2>
TL;DR</h2>
<div>
<br /></div>
<div>
I've extended the open-source IoT web-app development tool Evothings Studio by slapping on the open-source node-red flow-based editor and a number of custom modules to let you generate mobile web-apps with little or no coding, that let you connect to and communicate with Bluetooth devices.<br />
<br />
Downloads per platform;<br />
<br />
<a href="https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Win_32_2.0.0beta2-node.red.zip">https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Win_32_2.0.0beta2-node.red.zip</a><br />
<a href="https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Mac_64_2.0.0beta2-node-red.zip">https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Mac_64_2.0.0beta2-node-red.zip</a><br />
<a href="https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Linux_64_2.0.0beta2-node-red.zip">https://s3-eu-west-1.amazonaws.com/evothings-download/EvothingsStudio_Linux_64_2.0.0beta2-node-red.zip</a></div>
<div>
<br /></div>
<h2>
WAT</h2>
<div>
OK, so the short version goes like this; I work as a lead developer at a small startup called <a href="https://evothings.com/" target="_blank">Evothings</a>.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo2ZFJQG2YXEkquBxXngFyIK_9ggNLynYClTdOTGfTSLUFmvij7Qe8tAVB1WL7uu9XOvg6LfH63mgr9PMQd7ID7WVkiXN7n54-TSg0sO8ZSFq8OaSTyH6bHUsNc5exQxi2aSgfDMydysMr/s1600/evothings_logo_large_white1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo2ZFJQG2YXEkquBxXngFyIK_9ggNLynYClTdOTGfTSLUFmvij7Qe8tAVB1WL7uu9XOvg6LfH63mgr9PMQd7ID7WVkiXN7n54-TSg0sO8ZSFq8OaSTyH6bHUsNc5exQxi2aSgfDMydysMr/s200/evothings_logo_large_white1.png" width="200" /></a></div>
<div>
We mainly do two things; a number of cordova plugins for <a href="https://github.com/evothings/cordova-ble" target="_blank">BLE access</a> to weird things and sensors, and an open-source developer tool for IoT mobile web-apps called <a href="https://evothings.com/download/" target="_blank">Evothings Studio</a>.</div>
<div>
<br /></div>
<div>
The idea is to provide a workflow where you as a developer can iterate quickly using the <a href="https://github.com/evothings/evothings-viewer" target="_blank">Evothings Viewer</a> app (from either app-store) that connects to the <a href="https://github.com/evothings/evothings-studio" target="_blank">Evothings Studio</a> desktop application (both are open-source and on Github) so that the studio pushes any changed files in your projects out to the viewer, which reloads and send logs continually back to the studio.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9uVh315SouHRWtm0QwrEawbZK7dQbbz4CNiErPaIpa2pmu29_WXiRrK7LG2EvswEc4DdNiTQR07v2kNtVGcF6tepHU0q3GpbNmdTbYnlrBh4j6VcavkPgj0CCUexTd9RKBcYC1BajRcWO/s1600/ets2beta2.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9uVh315SouHRWtm0QwrEawbZK7dQbbz4CNiErPaIpa2pmu29_WXiRrK7LG2EvswEc4DdNiTQR07v2kNtVGcF6tepHU0q3GpbNmdTbYnlrBh4j6VcavkPgj0CCUexTd9RKBcYC1BajRcWO/s320/ets2beta2.JPG" width="320" /></a></div>
<div>
<br /></div>
<div>
OK, so far? Good. About now you'll wonder how we make money :). Currently we're just providing open-source projects and a free service (we have a proxy that let you connect your viewer(s) and your studio avoiding any client-isolation issues with local WiFi).</div>
<div>
<br /></div>
<div>
The basic service will always be free for small usage, but we're busy creating cool stuff on top of it that we hope people will find valuable early next year, or thereabouts.</div>
<div>
<br /></div>
<div>
Notice that the studio comes packed with a lot of IoT app examples, some geared towards specific hardware like Arduino, Eddystone beacons or the TI Sensor-tags. That's all open-source too and easy to copy to your own project to get a head start.</div>
<div>
<br /></div>
<h2>
So, about these visual boxes and stuff.</h2>
<div>
Right, right! OK. We got invited to IBM in Winchester a while back and while we talked about a lot of stuff, where one of the presentations got stuck in my head. It was a walk-through of another open-source project that IBM had created, called <a href="http://nodered.org/">node-red.</a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://nodered.org/images/node-red-screenshot-sm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://nodered.org/images/node-red-screenshot-sm.png" height="211" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Node-red is a flow-based editor that let you compose node.js programs visually, that then runs on the back-end when deployed. It's easy to install and try out and comes with quite a lot of cool components, like postgreSQL access, XMPP, MQTT, regular sockets, lots of other stuff - and at the end of the day you can deploy everything as a npm package.</div>
<div>
<br /></div>
<div>
What I was thinking was how cool it would be if one took node-red and added on top of it stuff that made it possible to create web apps, mobile, bluetooth enabled web-apps, specifically, and run them on a phone, incrementally while you're building it.</div>
<div>
<br /></div>
<div>
So I did that.</div>
<div>
<br /></div>
<div>
Or, more correctly, I started doing it. node-red has come quite a along way and it would have been a tall order to just implement all modules to work on the front-end, so I started creating custom modules instead. Modules are those boxes that show up in the visual editor that you string together to create flows.<br />
<br />
I needed a hierarchy of modules both to organize visual widgets and to define how messages are passed between modules (widgets or non-visible modules, like the bluetooth scanner), so I used the flow graph in node-red for both.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9nw_wJ_085O8gg_VqTPBc9E4-2OBhR9pTvneRmckdTP86bJX-9X1Rc_Yjc1p3JveA-Tc_qkoVKeXSA9aa_c30oZwT3Iwrk4HQL7gM0zO_6BkMEj5QfILPdw5Zy7RFjTdG_Y2eQTsasc_J/s1600/Screenshot-45.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9nw_wJ_085O8gg_VqTPBc9E4-2OBhR9pTvneRmckdTP86bJX-9X1Rc_Yjc1p3JveA-Tc_qkoVKeXSA9aa_c30oZwT3Iwrk4HQL7gM0zO_6BkMEj5QfILPdw5Zy7RFjTdG_Y2eQTsasc_J/s320/Screenshot-45.png" width="320" /></a></div>
<br /></div>
<div>
<br /></div>
<div>
The output of node-red is a single file called 'flows.json' which defines which modules are in the flow and any settings they have, in addition to how the modules are wired. I configured node-red to save the flows.json file in the home directory of the project being edited, and created a couple of open-source Github projects to make everything work together:<br />
<br />
nrmodules (Which are mostly just filler plugins for node-red that makes new modules show up in the visual editor, published also as a npm module):<br />
<a href="https://github.com/psvensson/nrmodules">https://github.com/psvensson/nrmodules</a><br />
<br />
nrfe (node-red front-end. Yes, I suck at naming things. Welcome to the club. This is the web-app side parser for the flows files)<br />
<a href="https://github.com/psvensson/nrfe">https://github.com/psvensson/nrfe</a><br />
<br />
nrfe-widgets (where the actual functionality of the modules happens. These widgets is what the parser wires together according to the flows file)<br />
<a href="https://github.com/psvensson/nrfe-widgets">https://github.com/psvensson/nrfe-widgets</a><br />
<br />
The 'widgets' depend on the cordova-ble plugin to be present in the mobile app running the web-app (in addition to cordova itself), so the following example app can't run by itself in a mobile browser - you either have to load it from the Evothings studio into the Evothings viewer app, or build it as a proper cordova/phonegap app:<br />
<br />
<a href="https://github.com/psvensson/nrfe-hello-world">https://github.com/psvensson/nrfe-hello-world</a><br />
<br />
The hello-world project also includes the nrfe and nrfe-widget projects as bower installs, so rmember to run 'bower install' at first and then 'bower update' to get any new widgets being authored.<br />
<br />
Some of the widgets are visual and are copied wholesale from the Material Design Lite library, and some (like the BLE scan) are not visual at all. Visual widgets need to be connected to a page or a section widget to be visible on the page, so for those kind of relations, the wires means something like a DOM hierarchy.<br />
<br />
For non-visual widgets and for visual widget outputs, the wires mean something else - they define how messages are passed between widgets/modules. So the Button widget 'OK' is wired to the BLE scan widget, which will toggle scanning for bluetooth devices, and in turn send a small JavaScript object defining the found device as output message, and so on.<br />
<br />
Please take this baby for a spin and let me know how hard you don't like it :) Or maybe what you'd like to see next. I'm planning to finish building modules for all bluetooth stuff like descriptors and next up is a module for MQTT.<br />
<br />
And if I don't find time to write a mode detailed follow-up article before new year's eve, here's some festive inspiration:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggwTMy2Y_bc4amcOX8qXZnXYH6NrAuQ_PI6J3zGz5sN5bRCpLDG0ELeV0ASk1pyObERozFnjJQsUhCqxf5MvbVpEP2OceMqaUDSoWr7_l-fNaO56sAxuzFuJDoAYPHRN3pJ-souRSzbyRg/s1600/czIUPmM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggwTMy2Y_bc4amcOX8qXZnXYH6NrAuQ_PI6J3zGz5sN5bRCpLDG0ELeV0ASk1pyObERozFnjJQsUhCqxf5MvbVpEP2OceMqaUDSoWr7_l-fNaO56sAxuzFuJDoAYPHRN3pJ-souRSzbyRg/s320/czIUPmM.jpg" width="320" /></a></div>
<br />
<b>EDIT:</b> I *did* find some time. So here is that 'how to get started' kind of article: <a href="http://unclescript.blogspot.com/2015/12/getting-started-with-visual-programming.html">http://unclescript.blogspot.com/2015/12/getting-started-with-visual-programming.html</a><br />
<br />
<br />
<br />
<br />
<br /></div>
Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-8028044062544098432014-07-10T05:43:00.002-07:002014-07-10T05:43:42.247-07:00Application routing, message busing and the irritating impossibility of programs as graphsI had a hard time writing that title. What I want to write about is a simple thing, but somehow it is quite hard to express.<br />
<br />
But to begin, I think that many programmers, like me, have a dream to some day do some or all of the following;<br />
<br />
1) A multi-user d&d inspired game<br />
2) A WYSIWYG web widget editor that 'just works' and create websites that can be generated in any of n languages or frameworks<br />
3) Some kind of 'mini-SOA' framework where the program is broken down into parts which are wired up with some kind of bus system.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://cfile3.uf.tistory.com/image/1865E91A4AA4C24E7546E8" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://cfile3.uf.tistory.com/image/1865E91A4AA4C24E7546E8" height="320" width="179" /></a></div>
<br />
These things usually crash and crash and crash again, again and again. I keep trying, keep crashing and even though I realize what I want to do is still a laughably long way beyond my skill level, it's still something that I strive to achieve.<br />
<br />
A couple of years age, thinking on one of these things, the application-routing, mini-SOA or, to call it by it's wiki-official name, dataflow programming framework (http://en.wikipedia.org/wiki/Dataflow_programming), I realized that it was practically impossible to create what I wanted.<br />
<br />
It might seem obvious to anyone else, but what I realized then was that if you wire up your application like a kind of graph, how do you define connections between dynamically created objects?<br />
<br />
Well, you can't, of course, or at least you have to break the circuit model, using some kind of API to programatically create connections, incidentally defeating the whole purpose of the framework.<br />
<br />
So dataflow wiring would only work for programs made up of singletons, which was a bother and made me retreat from further experimenting. Until yesterday.<br />
<br />
Again, this is probably super-obvious for anyone but me, but I just wanted to share my epiphany on why it's actually feasibly an indeed a very, very good idea to use dataflow abstractions for programs that create non-model objects dynamically (which most tend to do).<br />
<br />
What I realized was that in an UI (for example) there can be many levels of multiple objects created in hierarchies, but for every level, all objects can be treated as singletons, thus simple to wire up with a dataflow template.<br />
<br />
If one of these objects create a dynamic list of other objects, each of those objects will define a new 'level' or island, if you will, where all the relations can be wired up again using dataflow. So we have stable islands of instance relations, where one or more can create more islands, with implicit connections to them.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuQhPdB2r_Y9I_5G2QJ29PuxgThebDYJPXOClavCk9SHRa2Nooz2uOElT_btd2z18R-leWLDoPbbh2mHKX1pT3R2J8diANE_iepiTm8_erVHChyg5Cs9rGYBwQleEhC7yWATCXQHxvJrFC/s1600/Screenshot+from+2014-07-10+14:40:58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuQhPdB2r_Y9I_5G2QJ29PuxgThebDYJPXOClavCk9SHRa2Nooz2uOElT_btd2z18R-leWLDoPbbh2mHKX1pT3R2J8diANE_iepiTm8_erVHChyg5Cs9rGYBwQleEhC7yWATCXQHxvJrFC/s1600/Screenshot+from+2014-07-10+14:40:58.png" height="196" width="320" /></a></div>
<br />
<br />
One of my favourite dataflow architectures has been JDA (JavaScript Dataflow Architecture) which recently has re-emerged as construtcibl.es (http://docs.constructibl.es/specs/js/). I think what I'll do now is have a drink, look over JDA/constructibl.es again and see how it can be applied to Polymer, because Polymer.Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com2tag:blogger.com,1999:blog-7919361321436933137.post-27794203018444543502014-04-24T03:48:00.000-07:002014-04-24T03:50:55.572-07:00Five things your company should do with developer communities (but probably doesn't)Being a long-time developer community manager (Google Developer Groups) I'm often struck with how little companies care how they interact with the programming community, especially when it comes to sourcing and recruitment activities.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDOGY8c7KDWoTOC97GsNqz19Zp2nFgeP_QX-vi5Fj2GxKeE7IMc4zXRFMKlg5FVm8YeXeL1DKMDL2Zb3Qb15gLK0_KmZ981iaW_m2UHT4Z8J8wYDRkvB4-pfwckWuCHLVM7C9oPPjf9gPP/s1600/IMG_20131208_151528.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDOGY8c7KDWoTOC97GsNqz19Zp2nFgeP_QX-vi5Fj2GxKeE7IMc4zXRFMKlg5FVm8YeXeL1DKMDL2Zb3Qb15gLK0_KmZ981iaW_m2UHT4Z8J8wYDRkvB4-pfwckWuCHLVM7C9oPPjf9gPP/s1600/IMG_20131208_151528.jpg" height="240" width="320" /></a></div>
<br />
<br />
Most companies today are becoming more and more dependent on recruiting good developers, yet the way they communicate with the developer community remains very last-century.<br />
<br />
In essence, if you're letting your HR department or an external recruitment agency be the first point of contact with developers, chances are you're scaring away a good deal of them, who might have fit and thrived inside your company. You're essentially paying to become isolated from the very community you're increasingly becoming dependent upon.<br />
<br />
If you think this is a bad thing, here are my five top tips on how to interact with a developer community (I hope they will seem obvious after you've read them):<br />
<br />
<blockquote class="tr_bq">
<br />
<b>1.</b> Do proper research on which developer communities exists in the towns where you have offices (meetup.com is a great tool here), see which fit best with the technical skills you have the need for and consider asking your developers to create a new group if none exists.</blockquote>
<br />
<blockquote class="tr_bq">
<b>2.</b> Create incentives for your developers to a) talk at developer community events, b) host such events at your offices. This can be anything from perks to paid overtime.</blockquote>
<br />
<blockquote class="tr_bq">
<b>3.</b> Host at least one Hackathon each quarter in your offices. Make sure this is entirely planned and communicated by your developers.</blockquote>
<br />
<blockquote class="tr_bq">
<b>4</b>. Have your developers identify interesting / famous external developers who can be invited as speakers and let the developers invite as many people as can fit. This can be done perhaps once every quarter as well.</blockquote>
<br />
<blockquote class="tr_bq">
<b>5</b>. Create or host a developer game, where your developers interact with, evaluate and gets to know all other attending developers as part of the game mechanic. One great example is (full disclosure alert :) my own <a href="http://escapedevnull.com/" target="_blank">Escape from /dev/null </a>series of events.</blockquote>
<br />
<br />
If you do all these things - good for you! If not, know that many companies do and that they will get ahead of you in getting to know the best and the brightest developers.<br />
<br />
All of these things are related to developer branding, could be argued to be developer branding, but the more important thing is that they make your developers meet and interact with other developers. Everything else is details.<br />
<br />
You can have the best workplace in the world, but if you don't get the word out on a personal developer level, no one will know.Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com1tag:blogger.com,1999:blog-7919361321436933137.post-68172446940469940052014-02-08T01:34:00.000-08:002014-02-09T04:22:01.073-08:00Developer games - how do they work?If you're going to a developer game you might wonder how they differ from other kind of programmer pastimes like Hackathons, Programming competitions, just having a beer, talking and so on.<br />
<div>
<br /></div>
<div>
My definition (and as far I can tell I was the one calling these things 'developer games' in the first place) is this; </div>
<div>
<i><br /></i></div>
<div>
<i>A developer game is a combination of a programming competition and a computer game, where the challenges focus on the practical and fun rather than on algorithmic obscurity.</i></div>
<div>
<br /></div>
<div>
There are some algorithmic challenges from time to time, sure, and they can be quite tricky too. But the core concept is to have a welcoming, inclusive, little bit crazy event which you can attend to have fun and maybe win some prizes, but it's totally up to you and your team.</div>
<div>
<br /></div>
<div>
OK, so that's the overall picture, how does it work in practice?</div>
<div>
<br /></div>
<div>
All my <a href="http://escapedevnull/" target="_blank">'Escape from /dev/null</a>' developer games have taken place with everyone in the same room, or at least building, so that it's easy to ask questions and to interact with other people during the event.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha2xMlDQREJLXnc5aHUE1B7pSp3-SMaWORp8AWqnmo3Mk03-ZNMdLJ1uI5EWbLr36FoS2ROTu-eTlvgG2YLeWn7Z0Ihyphenhyphen0BSsT800d8WX8PxSEuYyqZzP6j0iUS1V_sBdj9QMG34MI-8dWr/s1600/IMG_20121020_092305.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha2xMlDQREJLXnc5aHUE1B7pSp3-SMaWORp8AWqnmo3Mk03-ZNMdLJ1uI5EWbLr36FoS2ROTu-eTlvgG2YLeWn7Z0Ihyphenhyphen0BSsT800d8WX8PxSEuYyqZzP6j0iUS1V_sBdj9QMG34MI-8dWr/s1600/IMG_20121020_092305.jpg" height="240" width="320" /></a></div>
<div>
When you arrive in the morning, you get login details to the game system and a reserved place to sit with your team. Then comes a general presentation about game mechanics, rules and how to play it in general, and then the system opens and off you go.</div>
<div>
<br /></div>
<div>
To the right is a picture from the presentation at a game I did at <a href="http://swdc.se/devnull/instance/devnull-valtech/" target="_blank">Valtech</a> in Stockholm a year back or so.</div>
<div>
<br /></div>
<div>
There are two different games, though; <b>The outer game</b> looks like something like this;</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5UybUg9rJdGpRdrfNe32TBV9gnNQLFgyvau6Kvf7NPnpb1jcPJD7SK3zlbsyAx4iEfmsmInlzEJvPgEHl8dYcuzHgrFnVbJYcJH_xOe9g6zuMdw2LUJg9OjkQMvb0FyG6HPl8QpBkUWbb/s1600/IMG_20121022_083354_crop.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5UybUg9rJdGpRdrfNe32TBV9gnNQLFgyvau6Kvf7NPnpb1jcPJD7SK3zlbsyAx4iEfmsmInlzEJvPgEHl8dYcuzHgrFnVbJYcJH_xOe9g6zuMdw2LUJg9OjkQMvb0FyG6HPl8QpBkUWbb/s1600/IMG_20121022_083354_crop.jpg" height="283" width="320" /></a></div>
<div>
The red text icons are team markers so that everyone logged in to the system can see where all other teams are on the map.</div>
<div>
<br /></div>
<div>
All teams begin at the same (or similar) location and can choose different paths to traverse the game-board to (hopefully) be the first team to snag the prize and the final node.</div>
<div>
<br /></div>
<div>
The nodes are the numbered circles and each node contains a programming challenge. Some nodes also contain prizes, so that the first teams to reach a node get the prize it contains (until there are no more prizes left on that node).</div>
<div>
<br /></div>
<div>
You can also see which nodes the teams are solving at the moment (white arrows) or if they have submitted a solution to the judges (red arrows) and how many minutes they have spent solving the problem (yellow numbers). The above game is an old game I've taken up to take a screenshot of, so the minutes numbers are quite huge, which is not normally the case.</div>
<div>
<br /></div>
<div>
OK, so say that your team gets a challenge, what does one look like and how does it work? I won't show you an actual challenge, but I will say that the challenges are thematic and most of them revolve around using a live web-based API where <b>the inner game</b> can be accessed.</div>
<div>
<br /></div>
<div>
For example the inner game can be (and have been) a multi-user space simulation where the team build a system one challenge at a time which controls a starship which can explore solar system, mine them and repair or build new things. </div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDnMke5-yHf3V1VN95HLXmry2zeKqqr5LCbwRXUHlOHNGTtBG_aPUzvu569_XmU-d3Cez3e4WVX8ipFk1A5nBmuj917oZRb9rMCZxQUVoP9b9MSbS2Rmz6hDSs36l-CEwvxISCY2m0sJTR/s1600/skepp2.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDnMke5-yHf3V1VN95HLXmry2zeKqqr5LCbwRXUHlOHNGTtBG_aPUzvu569_XmU-d3Cez3e4WVX8ipFk1A5nBmuj917oZRb9rMCZxQUVoP9b9MSbS2Rmz6hDSs36l-CEwvxISCY2m0sJTR/s1600/skepp2.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDnMke5-yHf3V1VN95HLXmry2zeKqqr5LCbwRXUHlOHNGTtBG_aPUzvu569_XmU-d3Cez3e4WVX8ipFk1A5nBmuj917oZRb9rMCZxQUVoP9b9MSbS2Rmz6hDSs36l-CEwvxISCY2m0sJTR/s1600/skepp2.png" height="320" width="226" /></a></div>
<div>
<br /></div>
<div>
The current inner game scenario is a multi-user rogue-like dungeon crawler, however. If you have ever played games like rogue, nethack, angband and the like, you know more or less what to expect - except it's in realtime, so monster do move even when you are not.</div>
<div>
<br /></div>
<div>
So let say that your team have solved a particular challenge, using the web-based interface you will then send of a short message to the judges who will then stroll down to your table and check out your solution.</div>
<div>
<br /></div>
<div>
If they spot a mistake or something that you've forgotten to do, the decline the submission and you have to give it an extra go or they accept the submission and your team is moved to the node which challenge you solved and you're free to choose a new one.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCY1M1XQHodZGrYxHrUdEs8I8QoNWZvWLw1ZiSVB5U6SqLYT9cxjAx3ILtOwd2p9XOXXcqjWJ3ydEKCPyUqGv972H2CRq5P2uo1A1W2Kr9BkatixWITRLL0-kibMBJLz3gVSZJcg6F6x57/s1600/IMG_20131123_124351.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCY1M1XQHodZGrYxHrUdEs8I8QoNWZvWLw1ZiSVB5U6SqLYT9cxjAx3ILtOwd2p9XOXXcqjWJ3ydEKCPyUqGv972H2CRq5P2uo1A1W2Kr9BkatixWITRLL0-kibMBJLz3gVSZJcg6F6x57/s1600/IMG_20131123_124351.jpg" height="240" width="320" /></a></div>
<div>
To the right is a blurry picture (I am so not a photographer) of what it looks like on everybody's screen when a team win a prize on a node.</div>
<div>
<br /></div>
<div>
You get to name your teams as you sign up and these guys decided to call themselves NullReferenceException (and was randomly assigned team code A02).</div>
<div>
<br /></div>
<div>
Another team in the same recent game called themselves "; DROP TABLE INFORMATION_SCHEMA; --", which was very optimistic :) I'm running Couch on the node.js back-end.</div>
<div>
<br /></div>
<div>
But the judging part takes us to the question of how and why the developer games exist at all. To fly all over the world setting these things up (not to mention buying prizes) costs a bit of money, so all events need sponsors.</div>
<div>
<br /></div>
<div>
And the whole reason I started doing these events was that I was so frustrated and dissatisfied with how development branding works when it comes to programmers. A lot of the communication is often done by a non-programmer who can't really represent the company properly and tend to brush programmers the wrong way.</div>
<div>
<br /></div>
<div>
What I would like companies to do (who absolutely depend on programmers) is to have more laid-back communication between their programmers and the actual programmer communities, and any evaluation should be done as respectfully and nicely as possible - and the best way I could think of was to create a cool, geeky and unique kind of game where programmer (the judges from the sponsor) meet programmers (the attendees) in a natural way.</div>
<div>
<br /></div>
<div>
The judges check out how you code and you get a chance to ask them how it's really like at the company they work for - if you want to. Many people just show up for the game and isn't really interested of the sponsor at the moment, but in a year or two that may change, and now they know who to contact.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0LyO2IUzSHUpaEr6qciOk32-dTOL0EJnS4dIHMwpOrzd1iDwk4X7np3HHtF3owzmWwB0VVcNiV_wxLZCMhrKTpMy2CTBQlrhQ9j4HEtMkBTCNjsbhjQRWRpyBgdWybFlaKleMW-hmyjw3/s1600/crop_EAHACK_03162013_crop_sm.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0LyO2IUzSHUpaEr6qciOk32-dTOL0EJnS4dIHMwpOrzd1iDwk4X7np3HHtF3owzmWwB0VVcNiV_wxLZCMhrKTpMy2CTBQlrhQ9j4HEtMkBTCNjsbhjQRWRpyBgdWybFlaKleMW-hmyjw3/s1600/crop_EAHACK_03162013_crop_sm.jpg" height="211" width="400" /></a></div>
<div>
<br /></div>
<div>
Also if you live in or near Seattle, the next game will have Hulu as a sponsor. More information can be found here; <a href="http://swdc.se/devnull/instance/devnull-hulu-2014/">http://swdc.se/devnull/instance/devnull-hulu-2014/</a><br />
<br /></div>
<div>
That's all really. Please ask any question you'd like in the comments if there is anything more you'd like to know</div>
<div>
<br /></div>
<div>
Cheers,</div>
<div>
PS</div>
Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-18764292271562382672012-11-12T01:05:00.000-08:002012-11-12T01:18:51.374-08:00Full Frontal 2012<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizk2_Yov72hohi95XDETS0QYiEju6bilfoQaV3JiU7RTFksa1iyYrkdKdiVIfx8ry4mSMzM3gMCHvDxzF8ItxgaLDRsE0f-YG59L5wUUuxKClpDMDRcmoRiftqGgWE-uvSpILjNdWq8CZh/s1600/IMG_20121109_170623.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizk2_Yov72hohi95XDETS0QYiEju6bilfoQaV3JiU7RTFksa1iyYrkdKdiVIfx8ry4mSMzM3gMCHvDxzF8ItxgaLDRsE0f-YG59L5wUUuxKClpDMDRcmoRiftqGgWE-uvSpILjNdWq8CZh/s320/IMG_20121109_170623.jpg" width="320" /></a></div>
<br />
Except for Google I/O, I never go to large or corporate conferences anymore. Since years back, I have by pure luck (or by being interested in the right things) found this complete gems, like the JSConfs in different reincarnations and regions, but closely snug together with them in my heart is the Sharp family's Full Frontal in Brighton.<br />
<br />
I was lucky enough to attend the very first one in 2009, just weeks after attending the first European JSConf in Berlin, being completely floored by Jake Archibald's deadpan, on-the-spot humor and Simon Willison's last talk who he had completely rewritten after seeing (as I did) Ryan Dahl present node.js for the first time at the previously mentioned JSConf. The energy and the passion of these guys completely floored me and I later found myself talking about them and the conf very often and for way too long.<br />
<br />
The boring terms for the magic sauce of Full Frontal is probably 'meticulously curated', but I really think that's what it is. It's a one-day, one-track conference with just the best of everything. I don't like all talks at all times, but most, I do, and not a little.<br />
<br />
I could go on about great moments from other years, but will instead just applaud this year's choices like Chris Wilson (above) who talked about his days creating the Mosaic browser and working on most versions of IE at Microsoft before joining Google two years ago. It was history. My own, incidentally, remembering downloading NCSA Mosaic from a local university FTP site and all things that have happened since.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPtqKN99UrJ4kuRzc6dQnXYH-fbBNOr0Cfd_ZKyz2jS4zef8Fs3qAdeCvQASi_nSoc7uFfTEt8T-NUHCqZ_Fv3-mFn-oPmwG58VHNvcMuDJbMAcn9rchyphenhyphen0xlwHF4UgCSeK6-Kfupg2aBH8/s1600/IMG_20121109_160955.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPtqKN99UrJ4kuRzc6dQnXYH-fbBNOr0Cfd_ZKyz2jS4zef8Fs3qAdeCvQASi_nSoc7uFfTEt8T-NUHCqZ_Fv3-mFn-oPmwG58VHNvcMuDJbMAcn9rchyphenhyphen0xlwHF4UgCSeK6-Kfupg2aBH8/s320/IMG_20121109_160955.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsEDuRhszZlVH6jUSmacOSaDtsoSTI-UquZNU2UyHtg25cbpDn49maiBBcHZKkbuJGM7LrAc3iPymBcHpYgMkNKS-M0BRpyG4Bk2bnDohkyYGkXeO0SRVUHKU4VRXk8j_MyIb2Tbsg47Zu/s1600/IMG_20121109_160940.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsEDuRhszZlVH6jUSmacOSaDtsoSTI-UquZNU2UyHtg25cbpDn49maiBBcHZKkbuJGM7LrAc3iPymBcHpYgMkNKS-M0BRpyG4Bk2bnDohkyYGkXeO0SRVUHKU4VRXk8j_MyIb2Tbsg47Zu/s320/IMG_20121109_160940.jpg" width="320" /></a></div>
<br />
But the speakers are one thing and the context and environment is another. The event always takes place at the Duke of Yorks' picture house, and old cinema in the middle of Brighton. For me it's very much a Groundhog day experience, but in a nice way. The weather is always coldish but not like it would be in Sweden, there's always a war memorial celebration about and I always stay at the same hotel.<br />
<br />
Also, my friends are there, new and old. There's lots of drinking (well, I am drinking anyway :) and gapping about important things (programming and SF&F). It's a very, very welcoming atmosphere (again very much like the JSConfs) with warm quirks like the sponsor Dharmafly who set up a rack with small potted plants to take home.<br />
<br />
I was nearly unable to go this year since I've done so much flying to promote the Escape from /dev/null programming competition (it sounds slightly meaningless at the surface but is really cool when you know more - hence the need to fly about) and I'd like to thank my wife for letting me fly *again* to goof off at a wonderful conference with my pals. I love you.<br />
<br />
Cheers,<br />
PSScript Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-31726198122318135202012-06-07T00:41:00.000-07:002012-06-07T12:03:05.948-07:00Konsulttimpriser i Stockholm (SWE)[ This post is in Swedish, so if you for some reason are interested in theories and statistics about what programmer consultants in Stockholm, Sweden gets paid, Google Translate is your friend. Normal service will continue shortly. ]<br />
<br />
<b>Uppdatering: </b><br />
<br />
@raiha skrev en mycket bra artikel för en månad sedan som också ger exempel på konsultpriser både för designers och programmerare: <a href="http://raiha.me/2012/05/freelancing-rates-in-stockholm-are-you-high-or-low/">http://raiha.me/2012/05/freelancing-rates-in-stockholm-are-you-high-or-low/</a><br />
<br />
@matshenricson Har också skrivit en relaterad, bra artikel runt timpriser (bl.a.) redan 2010; <a href="http://blog.crisp.se/2010/10/20/matshenricson/konsultmarknaden_behver_inte_vara_en_market_for_lemons">http://blog.crisp.se/2010/10/20/matshenricson/konsultmarknaden_behver_inte_vara_en_market_for_lemons</a><br />
<br />
<br />
<br />
<b>Vad är ett korrekt timpris?</b><br />
<br />
Förra veckan hade jag ett par olika mailkonversationer som direkt eller indirekt handlade om hur mycket det är rimligt att en konsult får i timmen för olika programmeringsuppdrag.<br />
<br />
Det ena gällde en bekant med mycket god meritlista som hade tagit ett uppdrag hos ett välkänt svenskt internet-företag för i mitt tycke ganska lågt timpris (700:-)<br />
<br />
Det andra gällde mig själv, då jag fick erbjudande om att göra ett kortare uppdrag innan sommaren åt ett företag där mina experkunskaper låg i fokus (OO JavaScript, HTML5 Canvas, mm) och mitt lägsta timpris (1000:-) visade sig vara på tok för högt. Noteras bör att jag har gått på detta i över ett år heltid och tar (och får betalt :) upp till 1400:-/tim för kortare uppdrag.<br />
<br />
Jag har länge haft en känsla av att avsaknaden av transparens i prissättningen gör det möjligt för olika dunkla vrår att bildas, men det kunde ju lika gärna vara jag som bara råkar ha haft en otrolig tur.<br />
<br />
<b>Tiden ur led.</b><br />
<br />
Rent objektivt sett har det aldrig varit svårare för företag att hitta rätt IT-kompetens, samtidigt som nästinpå samtliga företag blir mer och mer beroende av IT och sina system för att konkurera och i många fall finnas till överhuvudtaget.<br />
<br />
Reflekteras detta i konsulttimprisens utveckling de senaste tio åren? Nej, inte vad det verkar med dessa få mätpunkter.<br />
<br />
Jag inåg att det som behövdes var mer data, och gick raskt ut till alla mina kanaler och bad alla och envar att fylla i en snabb enkät jag hade skapar för ändamålet.<br />
<br />
Enkäten var anonym och informationen menad att göras fritt tillgänglig. Google Docs dokumentet som tog emot all data kan nås och laddas ner <a href="https://docs.google.com/spreadsheet/pub?key=0AhFzwqvEUKapdGwzSGxVRFJreDc1Wlh6UFduQ1JPWFE&output=html" target="_blank">här.</a><br />
<br />
<b>Allmänt om data.</b><br />
<br />
Jag gjorde frågorna ganska snabbt och skulle så här i efterhand tagit mig mer tid att tänka över fälten. T.ex. finns det inget sätt att ange hur kvalifierad man själv är som konsult. Det är dessutom fritext i fältet som bekriver updpragets längd, vilket leder till en del handarbete vid jämförelser.<br />
<br />
Det finns också en del outliers, som det heter på svengelska, bl.a. kodnamn "ereså" som glatt skriver in 200:- som timpris, vilket antingen måste anses som en anställd som med låg lön som konverterar denna lön till timmar, eller någon inköpare som försöker lägga in knasdata för att vikta till sin fördel.<br />
<br />
Det finns också åt andra håller en "Tt" som utger sig för att kamma hem 1800:-/tim för ett SQL uppdrag. Jag har träffat en person som har tagit (och blivit betalad) 1800:-/tim en gång, men dom växer inte på träd, så risken är att även den mätpunkten är lite tossig. [<b>Uppdatering: </b>Morten Nielsen har bekräftat att TT både finns och faktiskt tjänar så mycket!]<br />
<br />
Det var bara 129 personer som deltog i undersökningen den här gången (vara två är rekryterare som har mailat in exempel på för dom höga timpriser, som jag har lagt till längst ned), och jag vet inte hur pass statisktiskt signifikant mängden data är, men jag tycker en sak känns ganska klar;<br />
<br />
<b>Översiktlig analys.</b><br />
<br />
Det finns ett A-lag och ett B-lag. En stor grupp av konsulter harvar runt på 700-850, medan en annan grupp konsistent ligger över tusenlappen. Jag tror att uppdelningen i lag har mindre att göra med kompetensen hos konsulterna än hos inköparna. D.v.s de företag som känner till sina behov mer exakt vet också vad det är värt. Linjearbete skall man inte köpa in konsulter till.<br />
<br />
Sedan finns det de som antingen är gravt inkompetenta och/eller grundlurade som halkat under 700, vilket jag ser om en slags minimigräns om du skall ha konsultverksamhet överhuvudtaget.<br />
Anlednignen till den mer eller mindre fixa gränsen är att det är punkten där det blir möjligt att båda ge en schysst lön, spara pension och lägga undan lite pengar till investeringar.<br />
<br />
Under den ungefärliga punkten blir detta svårt och över den blir det plötsligt möjligt - lite grand som ångpunkten för vatten. Det blir en fasförändring.<br />
<br />
För de inköpande företagen, däremot finns det ingen ångpunkt. Det är bara en linjär ökning eller minskning av konstnaderna, och det är därför debatten är såpass viktig.<br />
<br />
Det innebär inte att jag tycker att 700:-/tim är en bra lön för alla konsulter, det innebär att jag tycker att det är en rimlig abslut minigräns ut till konsult. Där är ankaret. Frågan är sedan i nuvarande marknad inte hur lite en konsult kan ta betalt för att få jobbet utan hur mycket företaget är berett att betala konsulten för att anlita honom/henne.<br />
<br />
Båda parter verkar tro att de tjäner på att underhålla och prata tyst om siffror, men i själva fallet är det precis tvärtom. Ju mer hemlikghetsmakeri, ju mer kan enskilda företag pressa folk eller företag utan kontaktnät alldeles galet.<br />
<br />
<b>Jaha, men vad sa siffrorna då?</b><br />
<b><br /></b><br />
Medelvärdet, rakt av på timpris för alla angivna siffror blev 860:-/tim, vilket faktiskt vekar avspegla rätt väl ett normalpris i B-ligan.<br />
<br />
Annars är medelvärdet per kundtyp följande;<br />
<br />
<br />
B2B<span class="Apple-tab-span" style="white-space: pre;"> </span> kr 817.30<br />
Bank<span class="Apple-tab-span" style="white-space: pre;"> </span>kr 875.68<br />
Handel & Försäljning<span class="Apple-tab-span" style="white-space: pre;"> </span>kr 827.00<br />
Industri<span class="Apple-tab-span" style="white-space: pre;"> </span>kr 925.41<br />
Offentlig Verksamhet<span class="Apple-tab-span" style="white-space: pre;"> </span>kr 849.00<br />
Onlinetjänst mot konsumenter<span class="Apple-tab-span" style="white-space: pre;"> </span>kr 836.46<br />
Spel<span class="Apple-tab-span" style="white-space: pre;"> </span>kr kr 805.00<br />
Annat<span class="Apple-tab-span" style="white-space: pre;"> </span>kr 884.46<br />
<br />
<b>Din tur</b><br />
<br />
Ta gärna siffrorna och gräv fram mer data, och kommentera gärna nedan i största allmänhet.<br />
<br />
Mvh,<br />
PSScript Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com20tag:blogger.com,1999:blog-7919361321436933137.post-83100364050654975022012-04-15T08:03:00.000-07:002012-04-18T00:47:36.759-07:00Escape from /dev/null<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbnBFWlmnIvMJKXWh4AA5q_dpDw-cH-N84us9n3r0w0SWV9Et_TXw1-OL3KYDG3w9dbfdV8veXGnPx35QnsqTqvD03t4Ts8dRfXIcMOGQeqxa5SZY5O3xf2GUD06jKKI9Rd62SUhgSsOuc/s1600/radar2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbnBFWlmnIvMJKXWh4AA5q_dpDw-cH-N84us9n3r0w0SWV9Et_TXw1-OL3KYDG3w9dbfdV8veXGnPx35QnsqTqvD03t4Ts8dRfXIcMOGQeqxa5SZY5O3xf2GUD06jKKI9Rd62SUhgSsOuc/s200/radar2.png" width="141" /></a></div>
<b>Everything </b>began around summer last year, where I got the nth request from a company if I knew a good programmer who they could hire.<br />
<br />
I generally think that everyone should start their own companies, to get as much control over their lives and income as possible, but what have become more clear over time is that most people prefer the illusory safety of an employment over the guaranteed ambiguity of self-reliance.<br />
<br />
Even so, I wasn't really comfortable just handing over people or acquaintances to companies I sometimes knew very little about.<br />
<br />
Getting paid almost made things worse, and I realized I had a problem with the employment process itself (not getting paid as such:).<br />
<br />
<b>How</b> about instead of getting contacted by a person guaranteed not to be a programmer and who happily confuse Java and JavaScript, desperately trying to get you to come to an interview, one could create a meeting-place where the actual programmers of a sponsoring company meet and interact with other developers whom they might or might not be interested in hiring now, or in the future?<br />
<br />
The idea of the Escape from /dev/null was born. Yes, the name is cheesy, no it has little or nothing to do with anything at all. I like it anyway :)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPtJiFuv1LsOa3OdkyTSK-73FUNGwqAqhWB62UOGq6_2X4FFwEu61GEpwoFsLPgSo3XyVYuXT7vgFJlH9eIij4VgoSy2AowdeYjAgrHXeWo9oshqHJJewncZgw-Nr4kzgIkepnPbOKzkGP/s1600/6933732880_e026daa3b5_b.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPtJiFuv1LsOa3OdkyTSK-73FUNGwqAqhWB62UOGq6_2X4FFwEu61GEpwoFsLPgSo3XyVYuXT7vgFJlH9eIij4VgoSy2AowdeYjAgrHXeWo9oshqHJJewncZgw-Nr4kzgIkepnPbOKzkGP/s320/6933732880_e026daa3b5_b.jpg" width="320" /></a></div>
I wanted to create a game, where teams of players met in a ballroom where they got small programming challenges which got increasingly harder over time.<br />
<br />
Each cleared challenge let them move one step ahead on a public game-board, projected on a screen.<br />
<br />
<br />
<br />
<br />
<b>The</b> benefits for a sponsoring company are obvious;<br />
<ul>
<li>The competition would be interesting and fun enough in itself, being an actual programmers competition where one win prizes and not a recruitment event.</li>
<li>Instead of letting a programmer (who have lots of other stuff on his or her plate) spending time on a first phone-screen, writing up the results of that and then get three or four programmers to dedicate another half-day each for on-site interviewing under what I would call 'hostile' condition, they dedicate one whole day to interact with other programmers under playful conditions which still show the extent of their skills.</li>
<li>The marketing emphasize the recurring event, not the sponsor, in the same way that a recurring conference does, thus reaching out to developers who would not at first consider the sponsoring company as an employer but which after getting to know and work with the programmers of the sponsor during a whole day might think otherwise afterwards.</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4OA7P7u8UzGMhI-nP5yYDG8ha11B1rcIbykUlj9t7tlSAVJ94wJUTPfYYVmLk2EyvAyWYKOaLqw5ANEb9X3D-daaulABG2Mo3MMt2ws6wrwLfozn01MiNr4Y7fNGj3L3jvkSCWrJgzxop/s1600/6933737744_1651f9aebe_b.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4OA7P7u8UzGMhI-nP5yYDG8ha11B1rcIbykUlj9t7tlSAVJ94wJUTPfYYVmLk2EyvAyWYKOaLqw5ANEb9X3D-daaulABG2Mo3MMt2ws6wrwLfozn01MiNr4Y7fNGj3L3jvkSCWrJgzxop/s320/6933737744_1651f9aebe_b.jpg" width="320" /></a></div>
Unlike a Hackathon, competitive or otherwise, the process of a /dev/null event is as follows:<br />
<br />
Each team (this time we had two-person teams consisting of one front-end and one back-end person) has a similar starting point on a tactical map.<br />
<br />
The map represents a 'node' in the AI system of an alien artifact which has captured the spaceship where the attendees reside as crew.<br />
<br />
<b>However</b>, they are all trained system countermeasures specialists and know how to hack alien software. Lucky for them, eh? The only way forward is to reach the central node before the attack drones outside manages to breach the hull, by fooling the AI using ancient programming techniques known as 'JavaScript' and 'Python'.<br />
<br />
When the team chose their target node, they get a programming challenge. When they are done with the challenge they interact with the judges, who either send them back again or accepts their solution. They are then moved forward to their designated node and are free to choose a new destination.<br />
<br />
Certain nodes also contain artifacts, which can bestow powers onto the team or just prizes. This team all artifacts was prizes but I have some ideas in that area for future events.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlCHsRiWdbTvNCA5lXpbnqmNb5rO0jiKfp5Sqt22MSCjRFJlk6kU99pSEjZjuSqxKGh-zPoLeoc2VZhvC-9SHJneZ70tJ1qs9Y_b982i5M8EwwZJo4H-51AyUTQU0u0IdBPf46h0vLhcH6/s1600/6933735282_b5709098dd_b.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlCHsRiWdbTvNCA5lXpbnqmNb5rO0jiKfp5Sqt22MSCjRFJlk6kU99pSEjZjuSqxKGh-zPoLeoc2VZhvC-9SHJneZ70tJ1qs9Y_b982i5M8EwwZJo4H-51AyUTQU0u0IdBPf46h0vLhcH6/s320/6933735282_b5709098dd_b.jpg" width="320" /></a></div>
<b>Since</b> my co-organizer/Main sponsor this time was Spotify, we had a musically themed set of prizes.<br />
<br />
The only thing we gave away at the start was that the team that managed to reach the final node first would get one SONOS Play 3 music system each. SONOS was also a sponsor of the competition (along with Brooklyn Lager).<br />
<br />
The other prizes were kept secret until a team managed to win them, but ranged from concert tickets, custom-made Spotify headphones to decal and goodies Spotify bags.<br />
<br />
I had great luck in getting my friend Robert Hancock, Pythonista extraordinaire to both create the Python-specific challenges for the event, bot also actually come to Stockholm and speak at the beginning of the event!<br />
<br />
<b>Always</b> entertaining, full of stories and good humor, Bob did an excellent shortened version of his recent PyCon talk "Optimizing Performance with parallelism and Concurrency", which I felt really bad for giving such time-constraints.<br />
<br />
Even for a non-Python programmer, it contained not only nuggets but heaps of gold, with lots of computer and systems history thrown in for good measures. Good times!<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-ae_xwzyHkakwtCWeKHFpOqNSOCTyoTSd6BaXRmpCvgZRAU4775TEjBZqMcjiGMaExB2e2yRL0Ptpq1rn29sVYaPds9Lc6FKNaJZrysQ6JszzRsGLdxhYJxOCIfMIdYwiZiwEQy2MhRmQ/s1600/6933729564_08e4dcb4a9_b.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-ae_xwzyHkakwtCWeKHFpOqNSOCTyoTSd6BaXRmpCvgZRAU4775TEjBZqMcjiGMaExB2e2yRL0Ptpq1rn29sVYaPds9Lc6FKNaJZrysQ6JszzRsGLdxhYJxOCIfMIdYwiZiwEQy2MhRmQ/s320/6933729564_08e4dcb4a9_b.jpg" width="320" /></a></div>
<br />
I had an audacious idea to provide each attendee and team member with his or her own version of the game-board and interface instead of just moving around the pieces, showing off my dojox.gfx animation skills in the process.<br />
<br />
<b>Since</b> I had been late in finishing that part of the system, the fairly complex workflow needed do ask for a challenge, receive a unique (not the same one again, natch!:) challenge, send back a response, send it to one of the judges, wait for approval and finally get a success and automatic move to next node.. only almost worked.<br />
<br />
After trying it for a couple of hours, we decided to go with the original plan and just print the challenges, which in the end led to much more interaction between attendees and judges. Everyone could still log on to the system and get team movement, map changes, et.c. in beautiful websocket realtime, but the workflow needs some rehauling.<br />
<br />
Probably I'll set up a free online version of the system for smoke-testing when I have rewritten that part of the back-end.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjRjMRowbUDsQyXfNUTLEVkD4hf-bVdIoQEap6WxHFDlR120pWoIxTDYp82qEpzMqhvVJVOadUOkWaTuS3K2HxCb5VG7XZLqXIRVDqrrW_cGRlnEeLGuXihSVoOI9NlDbVyYlxxyUeFNP5/s1600/7079797083_4aa9ca1333_c.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjRjMRowbUDsQyXfNUTLEVkD4hf-bVdIoQEap6WxHFDlR120pWoIxTDYp82qEpzMqhvVJVOadUOkWaTuS3K2HxCb5VG7XZLqXIRVDqrrW_cGRlnEeLGuXihSVoOI9NlDbVyYlxxyUeFNP5/s320/7079797083_4aa9ca1333_c.jpg" width="320" /></a></div>
<b>All-in-all </b>everyone was very elated and had a great time. I think that my plan with small, specific programming challenges that could be done on 15-60 minutes was indeed a good one, and let to a good flow and friendly competition between teams.<br />
<br />
The Spotify judges were very professional and managed to adapt to changing game conditions without dropping a beat.<br />
<br />
Having Rikard, André and Jonas from Spotify there as HR groovemasters helped a lot, playlisting the venue (Debaser Medis) to a good programming mood as well as making sure everything moved smoothly. Big thanks!!<br />
<br />
The next planned /dev/null will happen in Amsterdam in the September/October timeframe, sponsor secret for the time being :)<br />
<br />
<b>Would </b>you or your company want to be a sponsor for an Escape for /dev/null event? Contact me at psvensson@gmail.com and we'll work something out. The system itself will be available for licensing/whiteboxing when done, before summer.<br />
<br />
If you are a recruiting organization that would like to offer /dev/null to your customers, there's a franchising option too :)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI4F1RKKsUAzWyVEYaU35APEARTTXchdy4BB7tAAqzB3219yKfjtCmmJzWlUoGjnntXIxnGCPL3dxL2_bPqg63tGccSJsqC58Nojiz8uKYXMFUkmab1EumT2-4_tgDQAs23keIa7nPvfs5/s1600/IMG_20120414_154933.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI4F1RKKsUAzWyVEYaU35APEARTTXchdy4BB7tAAqzB3219yKfjtCmmJzWlUoGjnntXIxnGCPL3dxL2_bPqg63tGccSJsqC58Nojiz8uKYXMFUkmab1EumT2-4_tgDQAs23keIa7nPvfs5/s320/IMG_20120414_154933.jpg" width="320" /></a></div>
<br />
I leave you with an action picture of team C07, the jaw-dropping trailblazer winners of the game this time. Me and the Spotify judges threw everything we had at them, but they just barged through challenge after challenge like they were thin paper (or in the end, fairly chunky carton, but still..). Kudos!<br />
<br />
<br />
<br />
<br />
<br />Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-30603729558928726322012-01-02T08:56:00.000-08:002012-01-02T09:00:02.347-08:00Simple Scaffolding for a Dojo Ajax Toolkit applicationI've been writing some simple exercises for workshop-style (or solo) training for Dojo Ajax Toolkit, focusing on the strength of Dojo - writing OO-JavaScript applications.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDyA_LKWC3-M65WZl1CYbgqad1hzVgYGUvIESM9__1KYplaYRGvgamGgLBiEaGvR30bd7fQciS-RgPjsWsXnZIdgDKvdOlUMRfQx3vJUOulMUBASCi2qDvFFlgCkoms0veMZzf5Xqs3FC2/s1600/99b4665b-1b1e-49c8-86f3-b5b5c81789b0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDyA_LKWC3-M65WZl1CYbgqad1hzVgYGUvIESM9__1KYplaYRGvgamGgLBiEaGvR30bd7fQciS-RgPjsWsXnZIdgDKvdOlUMRfQx3vJUOulMUBASCi2qDvFFlgCkoms0veMZzf5Xqs3FC2/s320/99b4665b-1b1e-49c8-86f3-b5b5c81789b0.jpg" width="320" /></a></div>
<br />
<br />
The first exercises is about using Dojo's (classical) require and simple namespacing to create simple widgets, but I've gotten repeated requests for a complete application skeleton - something I understand the need for and which would have helped me quite a bit some years ago as well.<br />
<br />
Luckily now there are some. The guys at Sitepen have written some excellent articles (with much better layout :) <a href="http://dojotoolkit.org/documentation/tutorials/1.6/recipes/app_controller/" target="_blank">here</a> and <a href="http://dojotoolkit.org/documentation/tutorials/1.6/templated/" target="_blank">here</a> which you should definitely check out as well.<br />
<br />
My aim here, though is to give you a scaffolding which contains all the structure you need to get started. I've included Dojo 1.7.1 in the latest exercise, which might seems staggeringly stupid, but the reason is that this part of the exercises will go into building and testing, where you actually have to have a downloaded copy.<br />
<br />
The exercises (definitely a work in progress) can be found here; <a href="https://github.com/psvensson/Dojo-Ajax-Toolkit-Free-Training">https://github.com/psvensson/Dojo-Ajax-Toolkit-Free-Training</a> and here is the Description file of today's app scaffolding sample.<br />
<br />
-----<br />
<br />
<br />
This exercise show how to make a simple scaffolding of an application in Dojo.<br />
It is not an exercise per se, but shows both a simple CSS layout and how to split up separate parts of the app into subclasses.<br />
<br />
This time we are referencing a local copy of Dojo 1.7.1, since subsequent exercises will use both the DOH testing system and the build system, both which are used from the Dojo 'util' folder<br />
and relies on parts of Dojo to run.<br />
<br />
I'm still using the old (pre-AMD) style of declaring classes, so Dojo will warn about some things.<br />
<br />
The goal is to show in a series of exercises how to create a simple single-page app with Dojo which is:<br />
<br />
1. Object-oriented - splitting functionality across a small class-hierarchy and through a logical namespace<br />
2. Using a sensible box model CSS layout<br />
3. Turn-key, so you can just copy the structure and get going modifying stuff as you please.<br />
<br />
The page sample.html require's just one class, which is the widget mycustom.MainApp<br />
<br />
In the MainApp class, a template is declared which defines the uppermost layout of the application;<br />
<br />
<br />
<blockquote class="tr_bq">
<div class="mycustom_box">
<br />
<div class="mycustom_box"><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><div class="mycustom_top"><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><div class="mycustom_left" dojoType="mycustom.navigator.ui.MenuBar"></div><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><div class="mycustom_right" dojoType="mycustom.common.ui.LoginWidget"></div><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span></div><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><div class="mycustom_center"><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><div dojoType="mycustom.navigator.ui.ViewPort"></div><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span></div><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><div class="mycustom_bottom"><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Bottom area<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span></div><br />
</div><br />
<div>
<br /></div>
</div>
</blockquote>
<br />
The application has three visual parts; A top part which contain a menu widget and a login/out widget, a central part which contains a viewport which can switch between different views, and a bottom part which contain information and links.<br />
<br />
Since these different parts are defined in their separate classes, with their separate template files, you get an automatic modularization that makes it less likely that different programmers<br />
step on each others toes when working together (or just one making a 10K lines long file...)<br />
<br />
This is a very, very simple scaffolding example which does nothing at all, but is a minimalistic proof of concept of how to start your own non-trivial Dojo application.<br />
<br />
The namespace is divided into the main parts 'common' - for classes that can be reused and are hopefully generic, and 'navigator' - for classes that are specifically implementing the logic of this application.<br />
<br />
I have called it 'navigator' because Internets. I have meant it to be a small app that let you navigate some space of stuff.<br />
<br />Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-77500224891862986422011-09-24T06:47:00.000-07:002011-09-24T06:57:59.565-07:00How to build Large Web Applications, part I<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGrGgw5HEUQhTIAy7oxbl1PM7g-E8Of5LiNmwhu_Agq2b5F37pCifW0MGbjjZ-afCXdpfNAjCV1s5RbrC-2MHGpLu9b5qdn5uPRaNAG5N98vFpCtZe42eKPiN6toomhFwO9o5ZtwNykgQP/s1600/playing-tennis-on-wings-of-plane-vintage-daredevils-black-and-white.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGrGgw5HEUQhTIAy7oxbl1PM7g-E8Of5LiNmwhu_Agq2b5F37pCifW0MGbjjZ-afCXdpfNAjCV1s5RbrC-2MHGpLu9b5qdn5uPRaNAG5N98vFpCtZe42eKPiN6toomhFwO9o5ZtwNykgQP/s320/playing-tennis-on-wings-of-plane-vintage-daredevils-black-and-white.jpg" width="320" /></a></div>
<b><br /></b><br />
<b><br /></b><br />
<b>I've</b> been busy the last two years building fairly intricate web apps for my customers and while it's a fun job it's also by necessity not public in the same way an open-source project is. The only comments I get and discussion I'm involved in are generally from my customers, so it's a bit of a closed loop.<br />
<br />
When I met Paul Irish in May this year in San Francisco he asked me,' But what do you actually do?', which was a fair question but took me by surprise. I'm mostly known for .. being that Swedish guy. With some luck people know I prefer Dojo as well, but I guess that's about it.<br />
<br />
So what do I do? I build web apps as an independent consultant. Sure, I arrange conferences and user group meetings too, but that's where my beer comes from, so to speak.<br />
<br />
This series of posts is both written to share and discuss what I feel are best practices around building large web apps, from a developer perspective, but also to let people know what I do. Possibly with the secretly evil intent of getting new customers if anything I write seems to be useful :)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1tjMpYPaoy0VrBI5NbZeZwLBAq-dFWPsGWpgCCgV1Q6RYyKra4fzUz4u9E52VrzmhFfNzrNYW_7MbR3w9qtSdZ-siNg9E9QsRHC7AbNMP-HYXFLPlF7xVO3qtimY4aRwLq-5IiaTHoHlD/s1600/3lsRs.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="104" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1tjMpYPaoy0VrBI5NbZeZwLBAq-dFWPsGWpgCCgV1Q6RYyKra4fzUz4u9E52VrzmhFfNzrNYW_7MbR3w9qtSdZ-siNg9E9QsRHC7AbNMP-HYXFLPlF7xVO3qtimY4aRwLq-5IiaTHoHlD/s320/3lsRs.jpg" width="320" /></a></div>
<br />
<br />
<b>Let's</b> begin with defining what a large web app is.<br />
<br />
A large web app (according to me, but please challenge and/or add to the list of items);<br />
<br />
<br />
<ol>
<li>Have composite views (showing both a static status area and a changing subview of items and lists, for example)</li>
<li>Have widgets that are variants of each other.</li>
<li>Have widgets that need to show up in dynamic configurations (e.g. a list of n, or each a always have a b except on Saturdays, ..)</li>
<li>Initializes communication with the server or service and caches some or all information.</li>
<li>Have widgets that need to change states, remember states and react to state changes in other widgets.</li>
</ol>
<br />
<br />
This list could go on and on, probably, but these are the most important things off the top of my head.<br />
One of my customers had an existing, successful product that was built in .Net C#. It was a client-server system where the client had the following features;<br />
<br />
<br />
<ul>
<li>Personal view of things going on, of various sorts.</li>
<li>List of personal things, arranged per time period in a tree structure, which showed a grid with the selected things.</li>
<li>Library of things of other people, arranged in a tree by both time period, user names and project names.</li>
<li>*very* complex search view where list of search queries could be build up dynamically and combined like date, project names but also other domain-specific (and visual) properties.</li>
<li>A thing editor which let the user compose a thing that was composed of various parts which could be dragged from a tab to the left and then changed according to their type and rearranged. There were parts like annotatable image, rich text, project reference, and so on.</li>
<li>Some of the parts needed access to the system clipboard for reading and writing, and some parts needed to start with and communicate with Excel. Several parts needed file access.</li>
<li>Lots of other, minor stuff.</li>
</ul>
<br />
And now, two years later, the Dojo/HTML5 version of the client have about 80% of the functionality of the old client (and some that it didn't) being sold to clients and everything. It's been quite a ride!<br />
<br />
I realize that I both want to cover the story of the programs creation and 'how to make large web apps' at the same time. It probably is a bad idea, but let's anyway.<br />
<br />
First of all, before digging into specific implementation I would like to talk about bare necessities. Stuff you just can't do without, stuff that if you are indeed left without it you will have to reinvent, poorly, and too late and botch things up completely. Yes, I have, and probably you too. But I didn't on this project(s) :)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxVKsbVUqwJzKVmJJXqEcwXdCGdiyUYWL43rbr0DTQaLLKqTYleIBLsHzixPHjx2DglKqdxLoFqIzUhLg30hQ9AWef0h3FpkH6JFxy58ut_RDcWHnLmtTNf5OLe6egRU4JH67HfMgtlKRn/s1600/image012_1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxVKsbVUqwJzKVmJJXqEcwXdCGdiyUYWL43rbr0DTQaLLKqTYleIBLsHzixPHjx2DglKqdxLoFqIzUhLg30hQ9AWef0h3FpkH6JFxy58ut_RDcWHnLmtTNf5OLe6egRU4JH67HfMgtlKRn/s320/image012_1.jpg" width="320" /></a></div>
<br />
<b><br /></b><br />
<b>Anyhoo,</b> If we take the first list of things that define a large web app, the items leads to certain demands on your tooling and libraries of choice. First of all you need to have a clean widget abstraction to work with, one that clearly modularize your code and your markup. It also help tremendously if you have a widget lifecycle metaphor, which is handled for you and that you can plug in to when and if you need to.<br />
<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Widget Abstraction</span><br />
<span class="Apple-style-span" style="font-size: large;"><br /></span><br />
<br />
The widget abstraction should, at minimum do the following (lots of lists, sorry);<br />
<br />
<br />
<ol>
<li>Separate code and markup, so you have a separate file or string for the markup of the widget</li>
<li>Make it possible to create widgets in classes that derive from each other, so you can have one grid baseclass, then a librarygrid that inherits from the basegrid, et.c.</li>
<li>Completely hide id allocation to elements and sub-widgets. By this I mean that the abstraction need to let you use symbolic names inside the markup (<div secretsauceproperty="foo">
</div>
) that are then used inside the widget class in lieu of id lookups.</li>
<li>Use markup replacement, so that parts of the markup is replaced with data in the widget class (<div>
${foo}</div>
will be replaced with this.foo in the widget before the widget is placed in the DOM)</li>
<li>Have a lifecycle so that when you create a widget, the widget "subsystem" / superclasses will call a number of functions on it that corresponds to the different event like a) init, b) before markup creation, c) after markup creation, d) before widget inserted into the DOM, et.c.</li>
</ol>
<br />
<br />
Dojo does all of this (as does several if it's peers (JavascriptMVC, Sproutcore, ExtJS, et.c.), but since the 'everything in a box' approach is a conceptual hard-sell, people generally want to use smaller and separate libraries that does just one thing, but well.<br />
<br />
A good, but a little bit dated list of a couple of markup libraries can be found <a href="http://www.viget.com/extend/benchmarking-javascript-templating-libraries/">here.</a> But markup libraries (like Mustache.js) only solves one of the problems.<br />
<br />
<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Dojo</span><br />
<br />
I'm going to cover a bit how Dojo works here, but please let me know in the comments if you know about stand-alone libraries for these functions. i would think that some are probably part of a larger library's class-system, but still.<br />
<br />
When I create a widget using Dojo, I create two files. One is the JavaScript class (obv) whic inherits from another custom widget or directly from dijit._Widget (widget subsystem) and dijit._Templated (markup replacement and symbolic element/subwidget naming). It could look like this;<br />
<br />
<b>In the directory "my/custom" the file "widget.js";</b><br />
<br />
<blockquote>
dojo.provide("my.custom.widget");<br />
dojo.require("dijit._Widget");<br />
dojo.require("dijit._Templated");<br />
dojo.declare(""my.custom.widget", [dijit._Widget, dijit._Templated],<br />
{<br />
templatePa<span class="Apple-style-span" style="font-family: inherit;">th: dojo.cache("my.custom", "widget.html"),</span><span class="Apple-style-span" style="font-family: inherit;"><br /></span><span class="Apple-style-span" style="font-family: inherit;"> <span class="Apple-style-span" style="color: blue;">username</span>: "nisse",</span><span class="Apple-style-span" style="font-family: inherit;"><br /></span><span class="Apple-style-span" style="font-family: inherit;"> postCreate: function()</span><span class="Apple-style-span" style="font-family: inherit;"> </span> </blockquote>
<blockquote>
<span class="Apple-style-span" style="font-family: inherit;"> {</span><span class="Apple-style-span" style="font-family: inherit;"> </span></blockquote>
<blockquote>
<span class="Apple-style-span" style="font-family: inherit;"> dojo.connect(this.<span class="Apple-style-span" style="color: #38761d;">mybutton</span>, this, function(e)</span></blockquote>
<blockquote>
<span class="Apple-style-span" style="font-family: inherit;">{</span></blockquote>
<span class="Apple-style-span" style="font-family: inherit;"> console.log("Someone pressed me button, eh?");</span><span class="Apple-style-span" style="font-family: inherit;"> </span><br />
<span class="Apple-style-span" style="font-family: inherit;"> }</span><span class="Apple-style-span" style="font-family: inherit;"> </span><br />
<span class="Apple-style-span" style="font-family: inherit;"> }</span><br />
<span class="Apple-style-span" style="font-family: inherit;"> });</span><br />
<span class="Apple-style-span" style="font-family: inherit;"><br /></span><br />
<span class="Apple-style-span" style="font-family: inherit;"><b>The file "widget.html";</b></span><br />
<span class="Apple-style-span" style="font-family: inherit;"><br /></span><br />
<br />
< div><br />
<div>
< button dojoAttachPoint="mybutton" >${username}< button ><br />
<div>
<div / ><br />
<br />
The 'postCreate' function on a widget is called (if present) just before the widget is placed in the DOM, but after all markup replacement have been done. We now have markup that contains a div with a button in it, and the content of the button reads 'nisse', since that was what the class variable 'username' contained.<br />
<br />
To use the widget you just have the following things in you code;<br />
<br />
<blockquote>
dojo.require("my.custom.widget");<br />
...<br />
var foo = new my.custom.widget();<br />
// Not mentioning argument passing or automatic placement in page stuff. it's just a widget in the wind right now</blockquote>
<br />
<br />
There a re lots of other things you can do, like automatic event wiring, but I hope this small example is just enough to make you think 'Hmm.. that could actually be kind of useful'.<br />
<br />
I am not really touching on the namespacing either, which is a simple things that have had ridiculous positive effects on the development speed and stability. We'll get to that later.<br />
<br />
What the widget will look like in the actual page is something like this;<br />
<br />
<blockquote>
<div>
< div><br />
<button id="mycustomwidget_0_mybutton">nisse</ button ></div>
</blockquote>
<blockquote>
<div>
<div/ > </div>
</blockquote>
<br />
<blockquote>
<div>
What's actually in the id is not important, the important thing is that the id is never visible to you (unless you really want to, but you don't. Why would you? The only thing you need is to get a reference to the node in question (in this case, to attach an event handler to it).<br />
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Also, what may be less apparent, is that when you customer want another widget just like it beside the first, you don't have to worry about widget id lookup code, you know that you abstraction will handle those details and just create a new one and smack it up - no problem.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
There are tons of more things I'd like to fit in here, but I have to clean the house while parts of the family is playing Deus Ex (the original) and others are off galivanting with horses. Oh well..</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Oh, right. I'll be doing a series of free, half-day Dojo-training events at Valtech in Sweden beginning the 13/10 2011. I'll post here (and on twitter etc) if you live nearby and want to learn the basics of creating custom Dojo widgets.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
See you soon!</div>
<br />
<br /></div>
</blockquote>
</div>
</div>
Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com13tag:blogger.com,1999:blog-7919361321436933137.post-58229720977775771732011-04-09T08:05:00.000-07:002011-04-10T01:57:19.070-07:00Bad, hairy, dangerous and irresponsible node+now+couch exampleWhat I feel is lacking many times when I want to learn a new piece of technology is smallest possible complete examples. I find many time how to interact with a new fancy database, or maybe how to communicate between client and server in a simpler, cooler way.<br />
<br />
Very seldom do I find examples that do everything I need. What I want, ideally, when toying with a new piece of tech is the following;<br />
<br />
1. Full instructions on how to set up any requirements, or at least pointers to good sources.<br />
2. Example of client code, or at least how to get a basic web page up through or in parallel to this new something.<br />
3. Example of how to call the service from whatever client should be used.<br />
4. Example of how to take care of the client requests send on the server-side<br />
5. Example on how to persist information and get it back again, even if that is not really part of the new tech.<br />
<br />
What I like to convey, I think, is that there is need for examples that give a newbie a fully working service for all examples, since even a very simple assumption can be to hard to grok if you are new to a certain scene.<br />
<br />
In general I'd think it is better to have working, fully stand-alone examples that one does not understand one bit, than to have an example that is a partial service that is easy to understand. The newbie is a coder after all, and as long he or she have a working example that can be thrown rocks at, eventually he or she will figure the stuff out.<br />
<br />
As it happens I've just manages to create (what I hope is) such a thing. What I wanted was to use the new <a href="http://nowjs.com/">now.js</a> socket.io client->server and server->client communications proxy. It's really sweet since it makes JSON-RPC calls really simple. it's like this;<br />
<br />
1. Your web page loads the now.js script from your now-powered node.js serverside JavaScript server.<br />
2. The server-script on the node side adds any property to the global 'everyone.now. object.<br />
3. JavaScript in your page gets any property changes propagated to a proxy object called just 'now' on the client.<br />
4. If the properties are functions, the client can call them, and the function call will be executed on th server. No setup code, no nothing. Just call the bloody function, thanks.<br />
5. If the client (your webpage JS code) adds a function of its own the server can call that.<br />
6. This is what you really, really want.<br />
<br />
If the browser doesn't support socket.io, a flash wrapper will be used, but all else remain equal.<br />
<br />
But then again, you really would want to have some database running wouldn't you? On the server-side, I mean. Couchdb, for example.<br />
<br />
What I just did was create a very small, not very clean example that uses now.js, couchdb and cradle on node and a small index.html file which load the now.js script and shows how to call functions exposed back and forth.<br />
<br />
The code looks like this;<br />
<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3MeabtndlmnxPDiKxM95G-vx7Ah_IQC7Po0uuHCzIK5NfmcK69P3o00iTJl2iFzanGjIIGB6U0-A4ZCy5EJzSnFPDieWpUJWI7Y-ItI2bYq1NwfzxqrH-bkZO_hrbY6374TqEyKLkvf74/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var url = require("url");
var sys = require("sys");
var path = require("path");
var fs = require("fs");
var inspect = require('eyes').inspector({styles: {all: 'magenta'}});
var cradle = require("cradle");
cradle.setup({host: "127.0.0.1", port: 5984});
var conn = new(cradle.Connection)();
var db = conn.database("abc");
db.create();
var yourHttpServer = require('http').createServer(function(req, response)
{
/* Serve your static files */
var uri = url.parse(req.url).pathname;
var filename = path.join(process.cwd(), uri);
path.exists(filename, function(exists) {
if(!exists) {
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not Found\n");
response.end();
return;
}
fs.readFile(filename, "binary", function(err, file) {
if(err) {
response.writeHead(500, {"Content-Type": "text/plain"});
response.write(err + "\n");
response.end();
return;
}
response.statusCode =200;
response.write(file, "binary");
response.end();
});
});
});
yourHttpServer.listen(8080);
var everyone = require("now").initialize(yourHttpServer);
everyone.now.msg = "Welcome to TEH wicked nowjs JSON-RPC";
everyone.now.foo = function(arg,cb)
{
sys.puts("Foo called.. arg and everyone.now is...\n");
inspect(arg);
inspect(everyone.now);
db.get('clientlog', function(err, doc)
{
inspect(doc);
if(!doc)
{
db.save('clientlog', {log: []});
}
else
{
var arr = doc.log || [];
inspect(arr);
arr.push({date: new Date(), message: arg});
doc.log = arr;
db.save('clientlog', doc,
function(err, res)
{
// Handle success
sys.puts("Error after save was : "+err);
})
}
});
cb( "server callback yo!");
}
everyone.now.bar = function(arg)
{
sys.puts("now.js function 'bar' called from client. args are..");
inspect(arg);
}
</code></pre><br />
<br />
<br />
What you need to do to get this working is;<br />
<br />
<span class="Apple-style-span" style="border-collapse: collapse; font-family: 'Droid Sans', arial, sans-serif; font-size: 13px;"></span><br />
<div style="color: #202020;">0. Don't have a lossy operating system.<br />
1. Install <a href="http://couchdb.apache.org/index.html">couchdb</a> and create a database named 'abc'</div><div style="color: #202020;">2. git clone <a href="http://nodejs.org/">node.js</a> + <a href="https://github.com/isaacs/npm">npm</a>;</div><div style="color: #202020;"><br />
</div><div style="color: #202020;"><span style="font-family: monaco, consolas, monospace; font-size: 12px; line-height: 16px; white-space: pre-wrap;"><span style="color: black;">git clone https</span><span style="color: #666600;">:</span><span style="color: #880000;">//<a href="http://github.com/ry/node.git" style="color: #67753a;" target="_blank">github.com/ry/node.git</a></span></span></div><div><span style="font-family: monaco, consolas, monospace;"><span style="font-size: 12px; line-height: 16px; white-space: pre-wrap;">git clone<span class="Apple-style-span" style="color: #202020;"> </span><a href="https://github.com/isaacs/npm.git" style="color: #67753a;" target="_blank">https://github.com/isaacs/npm.<wbr></wbr>git</a><span class="Apple-style-span" style="color: #202020;"><br clear="all" /> </span></span></span></div><div style="color: #202020;"><span style="font-family: tahoma, sans-serif;">./configure and make install first node, then npm</span></div><div style="color: #202020;"><span style="font-family: tahoma, sans-serif;"><br />
</span></div><div style="color: #202020;"><span style="font-family: tahoma, sans-serif;">3. npm install cradle (couchdb helper library)</span></div><div style="color: #202020;"><span style="font-family: tahoma, sans-serif;">4. npm install now (that thing I just talked about, sheesh)</span></div><div style="color: #202020;"><span style="font-family: tahoma, sans-serif;">5. npm install eyes (logging/inspect library)</span></div><div style="color: #202020;"><span style="font-family: tahoma, sans-serif;">6. Unzip the <a href="http://genericwitticism.com/nodestuff.zip">nowtest example zipfile </a>somwhere and do 'node nowtest.js'</span></div><div style="color: #202020;"><span style="font-family: tahoma, sans-serif;">7. Go to <a href="http://localhost:8080/index.html" style="color: #67753a;" target="_blank">http://localhost:8080/index.<wbr></wbr>html</a></span></div><div style="color: #202020;"><br />
</div><br />
Ta-daa! :)<br />
<br />
Or possibly not, since I just slammed this together. It's bound to have ugly, warty, beer-guzzling bugs. Please tell me about them so I can update the code and links. Thx!Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com2tag:blogger.com,1999:blog-7919361321436933137.post-6832398824886970412010-11-02T08:23:00.000-07:002010-11-02T08:23:11.878-07:00Ethics and Employment - part 1I've been thinking about employment for quite some time. It's a large topic and way too easily sway into the marshlands of politics. The first time I thought hard on employment was a year and a half ago.<br />
<br />
I realized that the company I worked for at the time didn't have the right connections to land the really cool JavaScript jobs which I was yearning for. I wanted to create true JavaScript apps and time and again I was shucked half on the side into a 'Web Project' where you had to massage the dark mystery horror server-side templates as per usual.<br />
<br />
This was not very fun. I liked the people I was working with but not what I was doing.<br />
<br />
The reason was the fact that I was sitting as a lame duck, wholly dependent on 'consultant routing' companies or my employer to give me something to do. Since they were basically blind to what a JavaScript client-side application was and I had few connections outside the people I happened to know, I was stuck in a loop.<br />
<br />
After arranging my first conference (SWDC 2009), and subsequently starting the Google Technology user Group of Stockholm I met with a lot of new people, one of who became my first customer, since they <i>did</i> want to make a JavaScript application. Quite a large one as well - a port of an existing .Net client-server app, but where the client should be remade in JavaScript and 'HTML5' with IE8 as a lowest boundary browser.<br />
<br />
I started my own company, took on the new customer and their project and I'm still working with them one year and four work packages later (albeit only two days a week, which was the idea at this point in the project). I had other customers as well, arranged another conference (Android Only) and generally made good money having a fair bit of fun :)<br />
<br />
The reason I do is because two things happened (painfully evident, but still);<br />
<blockquote><br />
</blockquote><blockquote>1) I finally managed to generate luck by meeting enough interesting people</blockquote><blockquote>2) I dared to bite.</blockquote><br />
And only recently have I realized what a sorry wretch I was before, not having any control over my working life and I felt that most possibly other people feel the same way. Generally, I've found out it's like this;<br />
<br />
<blockquote>1) You don't need to be employed at a company to get to work at great project and make good money, you only need to know enough people.</blockquote><br />
And if you don't know enough people, that's fixable. I feel that everyone should have their own company and interact with other companies as equals. To be an employee at a company is really not neccessary. Other than you own, that is.<br />
<br />
Another objection I have to being employed is that you get always get this half-decent salary that is capped, with your employer making as much money as possible on top of the cap, so to speak. I feel that employees should get a bigger share out of the profit they make.<br />
<br />
I've been part of profit-sharing schemes on different companies I've worked for, but none have really made any lasting impressions. I feel that as a subject area expert (and consultant) you should get at least 50% of the profit you generate. If you're become better, this will (or should) reflect on a higher hourly rate and an automatically higher salary.<br />
<br />
Having your own company gives you 100% of the profits of course, but not always as salary.<br />
OK, so what are the downsides? Lots, of course, but nothing that actually counts if you compare it to slowly becoming an old irritable grouch who is forced to do things he hate most of his working time. For example;<br />
<br />
1) Most of the time you only know about the next three months of revenue<br />
2) You are completely dependent on your customers<br />
3) You are completely epenedent on your customers paying you sort of on time<br />
4) You have no money when you don't work (i.e. 'vacation')<br />
<br />
So, in a nutshell, working on your own, you don't have any security whatsoever.<br />
<br />
Let me tell you a secret: Neither have you when you're employed, rounded down. <br />
<br />
The company can become bankrupt or on hard times, having to downsize as easy as your personal company would. The only difference between being an employee and owning your own company is that you actually have some control over the ship in the latter case.<br />
<br />
Even though this I do believe that you shouldn't be employed I have had two moral dilemmas; First of all Google. I have been a bit of a Google fanboy and despite having had my own company, I've applied for some positions there. This is clearly scizophrenic so I really hope I've stopped with that sort of stuff now :)<br />
<br />
The second moral dilemma has to do with employing people myself. Since I have quite a large network nowadays I get a lot of interesting offers that I rarely can do something about, being tied up in prior agreements.<br />
<br />
So, the natural solution would be to hand over those projects to other one-man shows for a small commission. Now for the suprising part; I can't seem to find these other one-man shows. OK, yes, I know of one, two at the most. I've been talking to great employed people I know, urging them to start their own company and start receiving project from me, but inevitably they shirk away from that and continue doing sort-of boring stuf (IMO) in exchange for apparent safety.<br />
<br />
This has led me to the very strange conclusion that if I want to give people projects, I have to employ them. OK, I *could* give the projects to the companies they work for now, but in most cases those companies are large, very <cough> executive and so on and so forth. I have a feeling I would not look good in the end, the projects having come to me sort of on a personal level. I would want to have some sort of responsibility.</cough><br />
<br />
So how do you employ people when you're against employment? :)<br />
<br />
Stay tuned for next chapter.<br />
<br />
Cheers,<br />
PSScript Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com5tag:blogger.com,1999:blog-7919361321436933137.post-12962335321636680332010-09-11T07:15:00.000-07:002010-09-11T07:15:27.756-07:00The problem-solving process in dynamic vs. static languages<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0EF8K62zO4cAoULC2TMVCJ8QkV7-EA3je-85xS9eDPEVUfLwBc0irCOWllo4hSrbCRqMaDF6gfMl6zIqZLPQZdSGLifmGtcE7GbTf4RfS8rKeUEFRgHvlhxJwkgcG9fk06WjB207hd3kq/s1600/MADb.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0EF8K62zO4cAoULC2TMVCJ8QkV7-EA3je-85xS9eDPEVUfLwBc0irCOWllo4hSrbCRqMaDF6gfMl6zIqZLPQZdSGLifmGtcE7GbTf4RfS8rKeUEFRgHvlhxJwkgcG9fk06WjB207hd3kq/s320/MADb.jpg" /></a></div><br />
<br />
This post is about why not to used static languages. It will outline the creative process used when starting to attack a problem and implementing its solution in code, and why that very process is hindered greatly by static languages.<br />
<br />
You know what I mean, when I say static languages (Java, Scala, C++, et.c.).<br />
<br />
I know that I've read about similar ponderings to these on the web earlier but a) I can't find them right now and b) It struck me anew on a personal level when I tried to understand why I work so much quicker when developing code in a dynamic language (especially JavaScript).<br />
<br />
<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;"><b>The dynamic development process</b></span><br />
<br />
When I start to formulate a solution to a problem in JavaScript, I focus on the algorithm, on the classes that operate on the data and their methods - on the flow of function calls between different parts of the system I build.<br />
<br />
Most often I forget some details about the data being passed or of what kind of state I need to include in the arguments in calls between different classes. This is no big deal as I just create new objects on the fly as arguments or return values, sometimes currying them up as part of a filtering process.<br />
<br />
This lets me stay 'in the zone' and focus on the problem I'm trying to solve. The data structures are pliable and can be changed in the same place as the code. I never need to bothered with what kind of data I'm juggling. I might do something like this;<br />
<br />
<br />
foo.barMethod({size: x, noses: 17, frotz: {a:'b', c:'d'}}, this.somethingImportantAtTheMoment);<br />
<br />
<br />
The first barMethod argument is an object. Just an object, could be anything. When I need to put more stuff in there, I do so. The object is so lightweight that it doesn't warrant its own class, it is really just a simple wrapper around some data I'm passing, pliable as my code for using it are right now in my problem-solving process.<br />
<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;"><b>The static development process</b></span><br />
<br />
This might differ significantly in Scala which I must confess I haven't studied enough. Please let me know in the comments if so. But when working with Java, I very quickly run into the creation of (often hierarchical) the definition of data classes and interfaces.<br />
<br />
Their properties are often complex, themselves objects, a couple of layers deep. Even though each data class is trivial, creating them takes me out of my creative zone, forcing me to make decisions around data that I'm not ready for yet. So naturally I put in the bare minimum of information.<br />
<br />
Then when using and passing around these objects, I often find myself constricted by the fairly arbitrary member/property types I've chosen, whose management tend to bleed out into the code, in the form of casts, et.c (This should be an area where Scala does help, though).<br />
<br />
When I change my strategies for my problem-solving logic, it impacts heavily on the contents and types of the data classes, even if the data and logic classes are the same. I need continually to pop out of problem-solving mode into yak-shaving mode to arrange the data to fit my new logic.<br />
<br />
I have now realized why static people so often tout the importance of having refactoring zombie-dust-powers in their extensive IDEs. From my vantage point it seems like fixing a language deficiency.<br />
<br />
But wait! What about all that evil terror that happens if you just create anonymous objects and functions mid-stride without any type enforcement? Well, for one thing - testing is key, and another thing - it has actually happened once or twice that I've had to hunt about in somebody else's code for what on earth they have put in an argument object.<br />
<br />
Compared to the extreme pain of always having a static retriever biting my private parts, the problem of finding the dynamic bottle of beer in the living rooms has in my experience been an extremely fair trade-off.<br />
<br />
YMMV, of course.<br />
<br />
Comments?Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com10tag:blogger.com,1999:blog-7919361321436933137.post-45142863788811120662010-05-01T09:22:00.000-07:002010-05-01T09:22:44.339-07:00A solid dyson sphere of Awesome; The JSConf experience<div class="separator" style="clear: both; text-align: center;"><a href="http://posterous.com/getfile/files.posterous.com/mahemoff/j6vhAIqlsAzrIiJ3OWY5VVVcfYHWbOLBeLy7nF1BqadkCICNSXSTP1KiGGrV/photo.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="http://posterous.com/getfile/files.posterous.com/mahemoff/j6vhAIqlsAzrIiJ3OWY5VVVcfYHWbOLBeLy7nF1BqadkCICNSXSTP1KiGGrV/photo.jpg" width="320" /></a></div>A couple of weeks ago I attended the second US JSConf in Washington. It turned out to be a very good move indeed.<br />
<br />
I can easily say that this was one of the best conferences I've been to, maybe the best one. The reasons are, I suggest, threefold;<br />
<br />
1) I have a personal, burning and possibly unhealthy interest in JavaScript.<br />
2) The speakers were generally critical-mass awesome.<br />
3) Track C - "The first rule of Track C is that you don't talk about Track C" - as Peter Higgins, president of the Dojo Ajax Toolkit has been known to tweet.<br />
<br />
Track C meant hanging around the corridors of Hotel Palomar, pilfering beer from pirate chests and having interstellar discussions about programming. And joking. And talking about SF books. Epic.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCgrKWiZ5C6GBK6OTqZsHYugnl0tvPxQ2J9xlAxV-KHAWGCmjkZjDf0SAiPB51ll1XZnbHAIm_9hIlg3dyM4aWCax8OtgeJbYM56r9nNdd1aXxhyXqSf_dfcQe9ejvSwlU0TjBVmAp4AX0/s1600/2010-04-17+13.20.29.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCgrKWiZ5C6GBK6OTqZsHYugnl0tvPxQ2J9xlAxV-KHAWGCmjkZjDf0SAiPB51ll1XZnbHAIm_9hIlg3dyM4aWCax8OtgeJbYM56r9nNdd1aXxhyXqSf_dfcQe9ejvSwlU0TjBVmAp4AX0/s320/2010-04-17+13.20.29.jpg" /></a></div>The playfulness and allowing atmosphere was really great and everywhere you turned you met guys and gals that also arrange their own conferences, write their own frameworks, turns the web inside out (or upside down), and so on.<br />
<br />
But last things first; After two days of extremely technical talks, games and panels, comes the final payoff - the keynote. What might the keynote bring, after node.js future directions, Sproutcore WYSIWYG editors, custom DSLs and JavaScript interpreters for Flash?<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivT8xy8rGEaHQlMGcLc3Mn-cvG7TNtWtOe67g_te76ObM3fB_opohLWQFiSxmHE6gOSSl5b-EgwJuGDZO5DS4YhS5t_MqALf2RUZAM5fhOOMFpBGRvNxR3_wmVPfd0zvKRbhWquVB50D54/s1600/2010-04-17+08.22.58.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivT8xy8rGEaHQlMGcLc3Mn-cvG7TNtWtOe67g_te76ObM3fB_opohLWQFiSxmHE6gOSSl5b-EgwJuGDZO5DS4YhS5t_MqALf2RUZAM5fhOOMFpBGRvNxR3_wmVPfd0zvKRbhWquVB50D54/s320/2010-04-17+08.22.58.jpg" /></a></div>In a word: 'Bacon'. Aaron Quint gave a Bacon keynote. No, it's not a framework or scrum-derivate-du-jour, actual cured pigs belly, that's what.<br />
<br />
Aaron is a foodie. He's a great Ruby and JS guy as well, but he is a very passionate foodie, and the level of passion and knowledge in his talk about making your own bacon, history of and how to barter it for microbrew was both entertaining and cheeky.<br />
<br />
Actually, the cheek belongs to Chris Williams, Pirate Captain of JSConf who, as always, risks all by choosing a *non-programming* keynote for a programming conference. That in it self was almost as fun as seeing it. Naturally Passion is key, and Aaron did weave in some pseudo-code to refer to the different experience of making food and making code. But the core of the talk was, IMO, about what makes us tick, as foodies, as developers and as human beings.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDq-USIl-qzKxDcO2nR2rwS6TwgSdPzOMo7AfNF_uBkzhASU1U_IfMjPWGE6iLWDdL3zG6B8BPcv2Wm1alP_Ed9_IJ9TGi7tJe_kPDBMXzrrzZ6vfK7_d40tsg-3d1IVu6uMTPz9F6dQiU/s1600/2010-04-17+08.48.58.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDq-USIl-qzKxDcO2nR2rwS6TwgSdPzOMo7AfNF_uBkzhASU1U_IfMjPWGE6iLWDdL3zG6B8BPcv2Wm1alP_Ed9_IJ9TGi7tJe_kPDBMXzrrzZ6vfK7_d40tsg-3d1IVu6uMTPz9F6dQiU/s320/2010-04-17+08.48.58.jpg" /></a></div><br />
Also, Chris actually planned JSConf together with his wife (who had a T-shirt with the text 'Pirate Pending' on), which was really nice and the very antithesis of Corporate.<br />
<br />
Another cool thing about the conference was that over 100 people who sent in their abstracts didn't get chosen. Actually, that is just the way it is and neither here, nor there, but since many people *really* wanted to get a place speaking at JSConf and vented some steam on twitter, Kyle Simpson (@getify) proposed having a pre-conference conference, the so-called Scurvyconf, which was open for anyone who couldn't speak at the actual JSConf.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDWrqSPTGBhVRVJx6F9hd7JBBwHDkkL0zDAzQwA91n0aaoj-jATboqdgLhpN-R7oCghPNEPQVgZFKsheWsPfv8rhaA91BTPJU7QkLmImgTO7pQFBl77UMoYQGEfNWpiz8ig-3vUVEttrSG/s1600/2010-04-17+11.45.35.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDWrqSPTGBhVRVJx6F9hd7JBBwHDkkL0zDAzQwA91n0aaoj-jATboqdgLhpN-R7oCghPNEPQVgZFKsheWsPfv8rhaA91BTPJU7QkLmImgTO7pQFBl77UMoYQGEfNWpiz8ig-3vUVEttrSG/s320/2010-04-17+11.45.35.jpg" /></a></div>The sound at the pub where ScurvyConf was held was deafening, with drunk geeks shouting over each other and having a generally good time. So the speakers had a hard time getting heard. This was taken in stride however and even though the audience participation was varied, it was very empathic where it occurred.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOg3wUIw93bImiLXk7L8EEKcqPGqDYSEUBbrNe2HD673WVQpgVJF2LqrgLQFtggw7C9AXhax-zR6zvZ0Naj95ktFsQ4JTVDJPVA3x4P1G89G7Nm3Eg18pQZImeZFrZRrBdHxWUx5Gn_m0x/s1600/2010-04-18+14.18.22.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOg3wUIw93bImiLXk7L8EEKcqPGqDYSEUBbrNe2HD673WVQpgVJF2LqrgLQFtggw7C9AXhax-zR6zvZ0Naj95ktFsQ4JTVDJPVA3x4P1G89G7Nm3Eg18pQZImeZFrZRrBdHxWUx5Gn_m0x/s320/2010-04-18+14.18.22.jpg" /></a></div>At the end of the first day we were treated to a cruise on the Photomac sponsored by Yahoo! with wonderful food and long discussions with people from Disney, Microsoft (Really!) and SinnerSchraeder (Hi Holger!) ranging from how XSS really works to defensive synthetic biology and the open wetware foundation. A total blast.<br />
<br />
I finally got to meet in person Justin Meyer, the creator of JavaScriptMVC who gave a great talk on its many strong points. My favorite is still the railsish generative scripts which creates client-side files for certain tasks (like consuming and displaying services). Justin was also the man who opened the bar in the wee hours of the morning on our way home from the final Google dinner night. Kudos for that (and spontaneous dancing to boot).<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3lzUx0ucpsNYg_2r9DHm6kmjV4RcJ5-SUzOgl3wWIyQRz7tugaxdnRrojf2rZ6jPcAjA9gvFk3pt9Lc2W-ygo78b-erS-PRa3TeaiuDcsCQzUCN8FkkWFEvrEf83pEOg2rH2lWwpYxh2P/s1600/2010-04-19+02.02.13.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3lzUx0ucpsNYg_2r9DHm6kmjV4RcJ5-SUzOgl3wWIyQRz7tugaxdnRrojf2rZ6jPcAjA9gvFk3pt9Lc2W-ygo78b-erS-PRa3TeaiuDcsCQzUCN8FkkWFEvrEf83pEOg2rH2lWwpYxh2P/s320/2010-04-19+02.02.13.jpg" /></a></div>When we finally got home, the final night, the idea was to go to sleep immediately. The ever-present pirate party had other ideas, however.<br />
<br />
There was vodkas and Guitar Hero and lots of falling into each other arms and crying, figuratively speaking, naturally.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizawCOqhTqa5sGQw0QO4GC96Z2Zuf4qSes9i3xyS_vcsrJbHufoCYdclVu5SHAhuWxkp1QnyouM7R0sOaG4nyeLQBvH1wB7Vg4VnjJeMIFwvYP5Vo-gYCYgWBpvGvtHzQpcv3pYIzh6jxm/s1600/2010-04-20+01.43.54.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizawCOqhTqa5sGQw0QO4GC96Z2Zuf4qSes9i3xyS_vcsrJbHufoCYdclVu5SHAhuWxkp1QnyouM7R0sOaG4nyeLQBvH1wB7Vg4VnjJeMIFwvYP5Vo-gYCYgWBpvGvtHzQpcv3pYIzh6jxm/s320/2010-04-20+01.43.54.jpg" /></a></div>We just had a great time. In fact, when I ran through airports the following morning, hungover like what have you, I was told that I had something hanging on my back. So I did. I let it hang all the way back to Sweden, and referred at least one person to Facebook who asked about it.<br />
<br />
It turned out, when I looked at my pictures, that I was not the only one so inflicted.<br />
<br />
I'll wrap this up now, and leave you with some more random pictures and a huge thanks to Chris and his pirate family for creating a completely stellar experience.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXEs8kELVQLmxrUQ8ZRNMc9tzjNH3I7oJZ8GQJcBtJ1OdFq3k2ABW3cgz5KuHfKyOHdkn9JFfNUv2D2u8GnTBIZTkMyaGLYM0w4jHPv7txdhrQWkD85w9lwxcGtz0fWc5Bp0KjZq6gEGzw/s1600/2010-04-19+03.08.00.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXEs8kELVQLmxrUQ8ZRNMc9tzjNH3I7oJZ8GQJcBtJ1OdFq3k2ABW3cgz5KuHfKyOHdkn9JFfNUv2D2u8GnTBIZTkMyaGLYM0w4jHPv7txdhrQWkD85w9lwxcGtz0fWc5Bp0KjZq6gEGzw/s320/2010-04-19+03.08.00.jpg" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz57bc8oKZSEwazLfrLuKI530sMGPCB8ZGc6kPefUFEzYFv49MixvGMzbyvgwOiFX2WF6JbDLhhGle0IpZKBrvz4fCrNHnjCfT9nE6-WZJ48q18cL6cl3OjllQpn1uuWaRL5c7jkk2ULbo/s1600/2010-04-19+03.05.15.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz57bc8oKZSEwazLfrLuKI530sMGPCB8ZGc6kPefUFEzYFv49MixvGMzbyvgwOiFX2WF6JbDLhhGle0IpZKBrvz4fCrNHnjCfT9nE6-WZJ48q18cL6cl3OjllQpn1uuWaRL5c7jkk2ULbo/s320/2010-04-19+03.05.15.jpg" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYA6ElvqbcOTqBU-_TpFysl7rkV8I-H7WJnmpFsjyjXjO5n-WcWSXWFIWjH7d_EtO6IRXK3ebftH_H_nDwXh7yEER_75fH9RQNmuFnjJOW098Hu1l6HvWXqEJ_D4Gtns8ZpQSMqb7JUT98/s1600/2010-04-17+15.14.02.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYA6ElvqbcOTqBU-_TpFysl7rkV8I-H7WJnmpFsjyjXjO5n-WcWSXWFIWjH7d_EtO6IRXK3ebftH_H_nDwXh7yEER_75fH9RQNmuFnjJOW098Hu1l6HvWXqEJ_D4Gtns8ZpQSMqb7JUT98/s320/2010-04-17+15.14.02.jpg" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5HHhtnc2I0RqqNg7wczG4pBp6BBdLCbdPOSes7mffujopwk6E7xDdy5xXzpi-w4BOknm5NHzJ110sh6B-3iL6xNSwsvraKMisPDXZI12M7AsxEmD2ehSoKp9xf0hLlq3pWaroo9hcnVba/s1600/2010-04-19+02.41.08.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5HHhtnc2I0RqqNg7wczG4pBp6BBdLCbdPOSes7mffujopwk6E7xDdy5xXzpi-w4BOknm5NHzJ110sh6B-3iL6xNSwsvraKMisPDXZI12M7AsxEmD2ehSoKp9xf0hLlq3pWaroo9hcnVba/s320/2010-04-19+02.41.08.jpg" /></a></div>Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com2tag:blogger.com,1999:blog-7919361321436933137.post-89426479807959098162010-02-28T07:42:00.000-08:002010-03-01T10:06:52.192-08:00Super-simple authentication using Google Friend Connect<div class="separator" style="clear: both; text-align: center;"><a href="http://code.google.com/apis/friendconnect/images/friendconnect_logo.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="313" src="http://code.google.com/apis/friendconnect/images/friendconnect_logo.png" width="320" /></a></div>I've been following Google friend Connect since it came out, since it's a very interesting API.<br />
<br />
For me, what's interesting about it has always been that it takes care of the authentication for a site owner. This is not the basic use-case, mind you. The basic use cases seems to be the simple addition of site-separate, rich, social widgets.<br />
<br />
This is by no mean bad, but the first thing I wanted to do with GFC was to just put up the first, simple 'join this site' widget, and then use the magic to let anyone who had a Google. Yahoo, AIM, OpenID, et.c. account just log in to my site, using a unique user id provided by Google.<br />
<br />
This proved quite hard in the beginning, especially since you basically had to learn a lot of OpenSocial APIs just to do something non-trivial. Since a couple of months back, the GFC APIs has become richer and also simpler. The meaning of this blog post is to show you in a simple way how to leverage GFC for your own authentication, without breaking a sweat.<br />
<br />
What you need to do is the following;<br />
<br />
<br />
<ol><li>Register your site with<a href="http://www.google.com/friendconnect"> GFC</a></li>
<li>Copy-paste in the HTML/Script code for the member gadget into your index.html page (This is done by selecting that gadget and choose to let the GFC page render the code including your site id in a copy-paste box. not terribly hard either).</li>
<li>Do nothing in particular, since the cookie will be send as part of each request to your server (even Ajax ones).</li>
<li>In your server, receive the cookie (looking like this: 'fcauth19038466278488110'), and call GFC from the server, suing the cookie, to get some info about the user.</li>
</ol><br />
<div><br />
</div><div>Using the following code, I make sure that the opensocial API is loaded and that I get a callback when it feels ready. It's not really necessary, but might be of use if you need to access viewer or owner info in your page before or without talking to the server.</div><div><br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
google.load('friendconnect', '0.8');
</code></pre><br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
google.friendconnect.container.loadOpenSocialApi(
{
site: 'xxxxxxxxxxxxxxxxxxxx',
onload: function()
{
var fcauth = dojo.cookie("fcauthxxxxxxxxxxxxxxxxxxxx");
console.log("gfc onload fcauth cookie was '"+fcauth+"'");
if(fcauth && fcauth != "undefined")
{
try
{
dojo.publish("ab_cookie", [fcauth]);
}
catch(e)
{
console.log("ERROR in opensocial access.."+e);
}
}
}
});
</code></pre><br />
Naturally, you can use an Ajax call inside the callback function directly. I've put all of my logic inside a custom Dojo widget, and if you're not using Dojo, you can do whatever you want.<br />
<br />
On the server, which I've coded using <a href="http://node.js/">node.js</a> and <a href="http://wiki.github.com/ry/node/modules">fab</a>, my handler function look like this;<br />
<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>Game.prototype.getUserInfo = function(fcauth, id, cb)
{
// http://www.google.com/friendconnect/api/people/@owner/@self?fcauth=<your fcauth>
log.info("getUserInfo called with fcauth='"+fcauth+"' and id='"+id+"'");
if(!fcauth || fcauth == "undefined")
{
log.debug("Skipping null/unathorized request");
}
else
{
var google = http.createClient(80, "www.google.com");
var request = google.request("GET", "/friendconnect/api/people/@me/@self?fcauth="+fcauth, {"host": "www.google.com"});
request.finish(function (response)
{
response.setBodyEncoding("utf8");
response.addListener("body", function (chunk)
{
sys.puts("BODY: " + chunk);
var echunk = eval("("+chunk+")");
if(cb) cb(echunk);
});
})
}
}
</code></pre><br />
</div><div><br />
You might choose Python or PHP on the server-side, but I hope that the code is fairly simple to understand. I have the specific code that extract the variables somewhere else, but the function is called with a couple of parameters, where one is 'cfauth'. This is the contents of the cookie set by GFC in the page before.</div><div>What the function does is call the GFC server with the cookie, using a special URL which gives back user information about the person just signed in using the cookie. We get back stuff that look like this;<br />
</div><div><pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>
{"entry":{"isViewer":true,"id":"16646299100122442145","thumbnailUrl":"http://www.google.com/friendconnect/profile/picture/9aOJATlcddBMuphbZq6wdLLqvyJr39BwuR60j67nPGv6LO8O_V3xho7gIoeH2juRoEm7jAOdl6_4RK4QAv5aFqD0zzg3TUxVAAZehjEoaEVTjeML9zwRyDFklaql_MxAznquk-Yhm63-ihZtryfA_T3tAwhWv4Szl12A1tZ3xfAa1jAdrE3it5Tx-fAbBW_qPZ3EE4DfALqLKmWC9hqXoXy9wI3rqzoS67CkgsTcU3CJM70ua9Z6OkIpFx7zi3dIXfIFawbodmOhKQ5A7_LeGA","photos":[{"value":"http://www.google.com/friendconnect/profile/picture/9aOJATlcddBMuphbZq6wdLLqvyJr39BwuR60j67nPGv6LNGCV3xho7gIoeH2juRoEm7jAOdl6_4RK11H5aFqDmikrg3TUxVAAZehjEoaEVTjeML9zwRyDFklaql_MxAznquk-Yhm63-ihZtryfA_T3tAwhWv4Szl12A1tZ3xfAa1jAdrE3it5Tx-fAbBW_qPZ3EE4DfALqLKmWC9hqcx0XswI3rqzoS67CkgsTcU3CJM70ua9Z6OkIpFuyzi3dIXfIFawbodmOhKQ5A7_LeGA","type":"thumbnail"}],"displayName":"psvensson"}}
</code></pre></div><br />
<div>I hope this helps someone, and apologies for not giving out all of my code, which is in a bit of flux.<br />
</div>Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com6tag:blogger.com,1999:blog-7919361321436933137.post-76075149274873600412010-02-11T03:12:00.000-08:002010-02-11T03:15:47.372-08:00[Swedish] rabatt till GTUG Stockholm medlemmar till Scandinavian Web Developer Conference 2010<span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px;"><br />
<img alt="?ui=2&view=att&th=12660e94d18e470d&attid=0.1&disp=attd&realattid=ii_12660e94d18e470d&zw" height="124" src="https://mail.google.com/mail/?ui=2&ik=213d69ae9c&view=att&th=126bcb821b8afa0c&attid=0.3&disp=emb&realattid=ii_12660e94d18e470d&zw" title="?ui=2&view=att&th=12660e94d18e470d&attid=0.1&disp=attd&realattid=ii_12660e94d18e470d&zw" width="320" /> </span><br />
<div class="gmail_quote"><div><div></div><div><span style="font-size: large;">Den </span><b><span style="font-size: large;">2 och 3 Juni</span></b><span style="font-size: large;"> går </span><a href="http://www.swdc-central.com/" style="color: #2a5db0;" target="_blank"><span style="font-size: large;">SWDC2010</span></a><span style="font-size: large;"> av stapeln på Skandia-teatern på Drottninggatan i Stockholm. </span></div><div><br />
</div><div><span style="font-size: large;">Konferensen för dig som vill lära dig det absolut senaste inom webb och mobilutveckling.</span></div><div><span style="font-size: large;"><br />
</span></div><div><span style="font-size: large;">[Detta information har tidigare gåt ut till GTUG medlemmar, men är nu uppdaterat med mer rabatt och enklare biljettprocess]</span></div><div><span style="font-size: large;"><br />
</span></div><div><span style="font-size: large;"><span style="font-size: small;">De främsta internationella experterna <wbr></wbr>inom Front-end utveckling, Mobil utveckling och JavaScript delar med sig av sina kunskaper.</span></span></div><div><span style="font-size: large;"><span style="font-size: small;"></span></span><br />
<span style="font-size: large;"><span style="font-size: small;"></span></span><br />
<span style="font-size: large;"><span style="font-size: small;"></span></span><br />
<span style="font-size: large;"><span style="font-size: small;"><div><br />
</div></span></span></div><div><span style="font-size: large;"><span style="font-size: small;"></span></span><br />
<span style="font-size: large;"><span style="font-size: small;"></span></span><br />
<span style="font-size: large;"><span style="font-size: small;"></span></span><br />
<span style="font-size: large;"><span style="font-size: small;"><div><b>DAG 1:</b> Fokuserar på front-end utveckling och JavaScript</div><div><b>DAG 2</b>: Fokuserar på programmering och utveckling av mobiltelefonapplikationer till framör allt iPhone och Android.</div><div><br />
</div><div>Du som har kommit på minst ett<b> GTUG Stockholm</b> möte får 875:- (25%) i rabatt på konferenspriset på <b>3500:-</b> (ex.moms), alltså bara <b><u>2625</u></b><u>:-</u> för båda dagarna!<br />
<br />
</div><div>Erbjudandet gäller fram till den <b>15 Mars</b>. För att använda dig av erbjudandet behöver du skicka ett mail från den epost-adress som är registrerad hos GTUG Stockholm till <a href="mailto:register@swdc-central.com" style="color: #2a5db0;" target="_blank">register@swdc-central.com</a></div><div>Som svar kommer du att få en engångskod som du använder under fältet "Coupons" på betalningstjänsten Stage HQ, som vi har länkat till från vår hemsida.</div><div><br />
</div><div>Mer information om konferensen finns att hämta på <a href="http://www.swdc-central.com/" style="color: #2a5db0;" target="_blank">http://www.swdc-central.com</a></div></span></span></div><div><br />
</div><div><b>Bland våra 15 talare:</b></div><div><br />
</div><div><img alt="?ui=2&view=att&th=12660c45c7a9ce97&attid=0.1&disp=attd&realattid=ii_12660c45c7a9ce97&zw" height="96" src="https://mail.google.com/mail/?ui=2&ik=213d69ae9c&view=att&th=126bcb821b8afa0c&attid=0.1&disp=emb&realattid=ii_12660c45c7a9ce97&zw" title="?ui=2&view=att&th=12660c45c7a9ce97&attid=0.1&disp=attd&realattid=ii_12660c45c7a9ce97&zw" width="92" /></div><div><b>Tom Hughes-Croucher </b>- Technical Evangelist/Innovation Lead på <b>Yahoo!</b> och expert på Accesibilitet och Web standarder.</div><div>Talar om : <span style="color: #222222; font-family: Myriad, Helvetica, Tahoma, Arial, clean, sans-serif; font-size: 12px; font-weight: bold;">Mobile Data: How to avoid the latency trap when using web services.</span></div><div><span style="color: #222222; font-family: Myriad, Helvetica, Tahoma, Arial, clean, sans-serif; font-size: 12px; font-weight: bold;"><br />
</span></div><div><br />
</div><div><img alt="?ui=2&view=att&th=12660c5ca6b2152e&attid=0.1&disp=attd&realattid=ii_12660c5ca6b2152e&zw" height="96" src="https://mail.google.com/mail/?ui=2&ik=213d69ae9c&view=att&th=126bcb821b8afa0c&attid=0.2&disp=emb&realattid=ii_12660c5ca6b2152e&zw" title="?ui=2&view=att&th=12660c5ca6b2152e&attid=0.1&disp=attd&realattid=ii_12660c5ca6b2152e&zw" width="96" /></div><div><b>Tom Blackmore</b> har arbetat med geospatiell data hos <a href="http://hitta.se/" style="color: #2a5db0;" target="_blank">hitta.se</a>, varit projektledare för <a href="http://hitta.se/" style="color: #2a5db0;" target="_blank">hitta.se</a>'s 3D-kartor, och håller en kurs i GIS på Mälardalens Unviersitet.</div><div>Talar om: <span style="color: #222222; font-family: Myriad, Helvetica, Tahoma, Arial, clean, sans-serif; font-size: 12px; font-weight: bold;"> Handling spatial data on the web.</span></div><div><br />
</div><div><br />
</div><div><b><img alt="?ui=2&view=att&th=1266a6542dfcda0e&attid=0.1&disp=attd&realattid=ii_1266a6542dfcda0e&zw" src="https://mail.google.com/mail/?ui=2&ik=213d69ae9c&view=att&th=126bcb821b8afa0c&attid=0.4&disp=emb&realattid=ii_1266a6542dfcda0e&zw" title="?ui=2&view=att&th=1266a6542dfcda0e&attid=0.1&disp=attd&realattid=ii_1266a6542dfcda0e&zw" /></b></div><div><br />
</div><div><b>Stefan Pettersson</b> är konsult på Netlight AB som JavaScript/Front-End expert och har arbetat på några av Sveriges största sajter, bl.a. Aftonbladet.se.</div><div>Talar om: <span style="color: #222222; font-family: Myriad, Helvetica, Tahoma, Arial, clean, sans-serif; font-size: 12px; font-weight: bold;">Developing Large-Scale JavaScript Websites.</span></div><div><span style="color: #222222; font-family: Myriad, Helvetica, Tahoma, Arial, clean, sans-serif; font-size: 12px; font-weight: bold;"><br />
</span></div><div>Se <a href="http://www.swdc-central.com/" style="color: #2a5db0;" target="_blank">http://www.swdc-central.com</a> för en komplett lista över talare!</div><div><br />
</div></div></div>Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com1tag:blogger.com,1999:blog-7919361321436933137.post-69325388254415992062010-02-01T10:55:00.000-08:002010-02-01T10:55:44.661-08:00GTUG Meeting January 2010<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy1byigdUXOLOhc0IjQAbqmO0pqf-5kNd4pwPaCJXbnHZONtIeTU6hNnoH7o1piPXPBm4tzprIzTtRqGNF6nLHDE_R2MSqo2GAyfRz4q9Ce2A4NsFgKWmtsI0ve5KniVphqcsC2WfMx1UL/s1600-h/IMAG0205.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy1byigdUXOLOhc0IjQAbqmO0pqf-5kNd4pwPaCJXbnHZONtIeTU6hNnoH7o1piPXPBm4tzprIzTtRqGNF6nLHDE_R2MSqo2GAyfRz4q9Ce2A4NsFgKWmtsI0ve5KniVphqcsC2WfMx1UL/s320/IMAG0205.jpg" /></a></div><br />
The January meeting got out of hand early on, as I got a semingly inocuous email message from a GTUG member asking if anyone from Google would be there to show the recently unveiled Nexus One phones.<br />
<br />
I asnwered that I thought it unlikely, but that I would give it a shot, and then forward the request to Tommy at Google Sweden.<br />
<br />
Not many minutes passed before I got a reply where he positively guaranteed that he or someone else would be present at the meeting, just the next week.<br />
<br />
When people got to know about this, we had a deluge of registrations, and for the nth time I became really tired with LinkedIn's feature-lack of limits for the otherwise hadny events that I used to use for GTUGs. In all, 93 people registered on the double machine check-in me and Ottoboni provided for the evening.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiatubFm0kMpEUBbFYfQykpdUpTPgQ7fML9DOJ3GlW3KtAc59iUuPqZvyq1_eIiKE0oiyO1rzCabaKT_9Jt-qKd8-xE_uLakdmoPjRQKfZtLZfrCHYosB3Cf68K1fSQKO-zxunL46B4sgRi/s1600-h/IMAG0219.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiatubFm0kMpEUBbFYfQykpdUpTPgQ7fML9DOJ3GlW3KtAc59iUuPqZvyq1_eIiKE0oiyO1rzCabaKT_9Jt-qKd8-xE_uLakdmoPjRQKfZtLZfrCHYosB3Cf68K1fSQKO-zxunL46B4sgRi/s320/IMAG0219.jpg" /></a></div><br />
First out was Ingemar Resare who talked about Google Apps integration, then came Tommy and Serge from the Google Office and totally winged an imprompty Nexus One presentation using their personal ones and answered hudnerds of questions.<br />
<br />
I had to break somewhere in the possible middle of the question train since people started getting restless, eyehing the sandwhich trays (OK, so I was hungry, sue me :)<br />
<br />
The food break was on the other hand a natural time for people to get to thold and try out the Nexus One themselves, with a Sandwhich or beer in the other, possibly both.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLQ1sndL3y6btmuWOCbloUF0MI1cMAZrF7wkPyC_LXQnmxjM11E424hE9kVvfxSCeQsU0lKeWqF4UOIuDtXWwA-siXM1PGwl1tbRM2YfO6pt47YtUB46024lEW49G57KCEYx0GGj69faEx/s1600-h/IMAG0234.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLQ1sndL3y6btmuWOCbloUF0MI1cMAZrF7wkPyC_LXQnmxjM11E424hE9kVvfxSCeQsU0lKeWqF4UOIuDtXWwA-siXM1PGwl1tbRM2YfO6pt47YtUB46024lEW49G57KCEYx0GGj69faEx/s320/IMAG0234.jpg" /></a></div>To the left here is Tommy describing the Nexus one's features.<br />
<br />
For our last number, we got Peter Sönnergren who did an outstanding App Engine + Java talk which led to a lot of questions and I think perhaps the first real walkthrough for many present.<br />
<br />
He was promptly talked to by the arranger of JFokus (which was due the very next week) and it turned out that he not only appeared on stage (together with Patrick Chanezon, I think) and also took over a Groove on App Engine session, sicne the Groovy guy had falled unexpectedly sick at the day of the talk. Talk about pivoting!<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqlddKGa-jbJABt4ezyuO-EanQSSm5pMbik2KEfaXpBcIURnxAznsljiWg_hgu2UV53PK3ETXUTwVzy4XX67bcG90QV8XJrKg5gjRwnHVx1mky0hstKJTPlcAw8X8ctCDTIYkLIEF8MGqD/s1600-h/IMAG0241.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqlddKGa-jbJABt4ezyuO-EanQSSm5pMbik2KEfaXpBcIURnxAznsljiWg_hgu2UV53PK3ETXUTwVzy4XX67bcG90QV8XJrKg5gjRwnHVx1mky0hstKJTPlcAw8X8ctCDTIYkLIEF8MGqD/s320/IMAG0241.jpg" /></a></div>Gotta keep this short, but now you know what was going on. And actually, the next GTUG meeting is this Thursday - completely packed as well, since we will both host Spotify's Anders Bond who will talk about their Android development process, and as a little extra number.. <br />
<br />
An Actual Android Developer Codelab with breakout coding sessions and everything led by Reto and Billy from the Google Developer Advocate Android team. Check out their schedule <a href="http://sites.google.com/site/androiddevlabs/home">here</a>. Sweden is just part of the big show that's going down right now.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQbwG06MNut9CFuf0175Hu8RcZBLTnJf-0kifW_R4LrfT6VH6SrN2tfKssxshNkS-Txjf-eq8jEmPGSnK01VgIY5nIKCjyNFlR-VMtJm42e6u9cC4McQc58OvNzZnunv9bVYeWYxGYJjyG/s1600-h/IMAG0245.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQbwG06MNut9CFuf0175Hu8RcZBLTnJf-0kifW_R4LrfT6VH6SrN2tfKssxshNkS-Txjf-eq8jEmPGSnK01VgIY5nIKCjyNFlR-VMtJm42e6u9cC4McQc58OvNzZnunv9bVYeWYxGYJjyG/s320/IMAG0245.jpg" /></a></div><br />
But we'll have a meeting in March as well - at the Google Sweden Office (allegedly).<br />
<br />
<br />
Cheers,<br />
PSScript Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-32757874645132104352009-12-29T04:49:00.001-08:002009-12-29T04:49:38.678-08:00A new term for what we do<div class="separator" style="clear: both; text-align: center;"><a href="http://www.shawnmcnulty.com/art/L/perseverance_red_abstract_painting.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="150" src="http://www.shawnmcnulty.com/art/L/perseverance_red_abstract_painting.jpg" width="200" /></a><br />
</div><br />
I started a new part-time project a while ago where I was allowed to use the full power of thin server architecture and Dojo, where the back-end was written in PHP.<br />
<br />
While talking about the architecture with the back-end developer (which was really impressed about the cleanness of using a <a href="http://groups.google.com/group/json-schema/web/service-mapping-description-proposal">SMD</a> file to define the protocol contract between client and server) we compared experiences and realized that we were both programmers first and visual designers last, if at all.<br />
<br />
Many times the customer or project owner have a very dim understanding of client-side development, which leads to bizarre ideas about the simplicity of implementing ideas in the browser. Most common is that JavaScript is seen as something to use as a last resort and that the entire user experience is seen as a series of 90s cardboard static HTML pages, mainly because it's simpler to conceptualize, I guess.<br />
<br />
Working the majority of my time with web pages but never with visual design means that I need to find very advanced customers and project members who understand that there is a layer below the design, but not on the server.<br />
<br />
And that's when the expert PHP developer I was working with (Henrik Hussfelt, no less) coined the term <b>middle-end developer</b>. I have never heard that before, and IMO it resonates with where I put myself in the value stack.<br />
<br />
Could a new definition like middle-end be a tool to more precisely define the JavaScript programmers role; Not as someone who adds an event handler to a button, but someone who creates the actual client application, but not the markup template for it.Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com3tag:blogger.com,1999:blog-7919361321436933137.post-81715017084714268942009-12-14T05:02:00.000-08:002009-12-14T05:02:21.088-08:00GTUG Stockholm meeting December 2009Like the happy crazy people we are, we had a GTUG meeting only days after the Android Hackathon. The upside of that was that we could have a recap for those unfortunates who didn't have the time or ability to attend.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDj2UK-ZOouTIWKMJ3jqqH73CSE3EDkKMNZSEGZvrr3RzQSBf6NxwfyR0n8zfiCTRgXXp3coFvIAYhiwR-8-4Abnr3r9fBE5K4Om4o46I_UZH0nZLhiE4OtUboHVPfJ0bTO68EF-PKxauH/s1600-h/IMAG0175.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDj2UK-ZOouTIWKMJ3jqqH73CSE3EDkKMNZSEGZvrr3RzQSBf6NxwfyR0n8zfiCTRgXXp3coFvIAYhiwR-8-4Abnr3r9fBE5K4Om4o46I_UZH0nZLhiE4OtUboHVPfJ0bTO68EF-PKxauH/s320/IMAG0175.jpg" /></a><br />
</div>About 30 people came, which is OK, but made me think maybe we should do the meetings bi-monthly instead of every month. Not sure either way, but I'll decide after next meeting.<br />
<br />
The people who came were as always from a lot of different companies; Spotify, formerly of Spotify, Voddler, Qbranch and many others.<br />
<br />
After my short introduction and talk on some new Google technologies (Mostly Closure) Tommy Widenflycht from Google Sweden did a talk on Google recruitment and then answered questions for a long time, handing out frisbees and hats to the best ones.<br />
<br />
Apparently, there's a need for really talented Server-Side coders (C++/Java) and A/V Codec programmers in the Stockholm office (and elsewhere). If you feel that you fit the bill, contact me by direct email (psvensson@gmail.com) or comment this post and I'll make sure you get to talk to the right people.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe2o-Ft84aF-gGDYfVXgu4LrH0kWDk6GWRAj4CZFsb4TMxcRJtwwSpwax2FZ6rCmMAIX9URnslmzfZuL0ufRGAxlHdhK5uLKYEYQZ9BuUkjanzJjjBm8uGiFoFBUBTgYXjKzIF65y05Gzm/s1600-h/IMAG0181.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe2o-Ft84aF-gGDYfVXgu4LrH0kWDk6GWRAj4CZFsb4TMxcRJtwwSpwax2FZ6rCmMAIX9URnslmzfZuL0ufRGAxlHdhK5uLKYEYQZ9BuUkjanzJjjBm8uGiFoFBUBTgYXjKzIF65y05Gzm/s320/IMAG0181.jpg" /></a><br />
</div><br />
Then it was time for the much-anticipated JavaScript on Android talk by <a href="http://divineprogrammer.blogspot.com/">Mikael Kindborg</a>. I was really impressed with the research Mikael had done and what he had managed to do.<br />
<br />
First he had compiled Rhino for the Dalvik VM and used that to parse incoming JavaScript string. So far, so good. To do that he had made a simple JavaScript app server called RhinoDroid (You can get it<a href="http://github.com/mikaelkindborg/RhinoDroid"> here </a>from github) that made it simpler to push JS from an external source (like a browser, or in Mikael's case, the Squeak Smalltalk environment. That's was really cool in itself. What happened then I could have understood if I had thought about it, but I hadn't had the time.<br />
<br />
Since all Android APIs (that has been compiled into the RhinoDroid app) are accessible by the JavaScript script when running, Mikael showed how he could build up a simple Android interface asynchronously, adding some buttons, which popped up on the Androdi screen, push those a bit - nothing happens.<br />
<br />
Then send some JavaScript event handlers that bind to those buttons, which get dynamically evaluated and then the button do something. So he was building an Android UI - and changing it - in realtime. Think about that for a while.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjadTyDPrbM-zRc5K91QOP_SaxcUqf_dxfc4HH5i5wb9hTVv1nGM1CpvVrpLQwKhBUFxY8Rpu0NcprOfA1vHIsEkyQWa9XJ0v_MHh2JGX9ZUxigGGPpOoaiyi1H9EXF909ad3qgnSo5eBRs/s1600-h/IMAG0184.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjadTyDPrbM-zRc5K91QOP_SaxcUqf_dxfc4HH5i5wb9hTVv1nGM1CpvVrpLQwKhBUFxY8Rpu0NcprOfA1vHIsEkyQWa9XJ0v_MHh2JGX9ZUxigGGPpOoaiyi1H9EXF909ad3qgnSo5eBRs/s320/IMAG0184.jpg" /></a><br />
</div>The next talk was Johan Burell who did a run-down of the <a href="http://unclescript.blogspot.com/2009/12/gtug-android-hackathon-2811-2009.html">Android Hackathon the previous Saturday;</a> Which apps had been created, which ones had _almost_ been created, and so on. Several people who had been present was in the audience as well, so we had some recaps and discussions about team @froderik's Android Hudson front-end and the other apps as well.<br />
<br />
The last talk for the night was by Sony Ericsson's strategy manager Thomas Bailey, who did show and pass around an actual X10 Android phone. It's surprisingly and reassuringly heavy and a screen that is 'right' sized. The interesting parts of Thomas' talk was the fact that Sony Ericsson is starting their own Android App store, to be able to offer developers a more controlled environment to publish their apps to, and Sony Ericsson's signature apps (Organizing and formatting activity streams and media) which will exist only on their phones but can be extended using XML files, which will pop in future sources of contacts, media and other things, which is a neat concept in itself.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfa0KRRQsHpM78xWY3HWHA_Mga5gD_1HPBKSTTV2GBMJqRVzubzrEb9Wb6iLn2k8FK6PtSiJLYaFv674LH38_nhIlTds69NMOTrtjtJzojEKTNsYdJ28MiQaUBieVSjKk-llX3k855GE3c/s1600-h/IMAG0189.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfa0KRRQsHpM78xWY3HWHA_Mga5gD_1HPBKSTTV2GBMJqRVzubzrEb9Wb6iLn2k8FK6PtSiJLYaFv674LH38_nhIlTds69NMOTrtjtJzojEKTNsYdJ28MiQaUBieVSjKk-llX3k855GE3c/s320/IMAG0189.jpg" /></a><br />
</div><br />
Our next meeting will be on <a href="http://events.linkedin.com/GTUG-Stockholm-January-2010/pub/180846">January 14th</a>, where we will cover the following topics:<br />
<br />
<span style="font-family: Arial, Helvetica, 'Nimbus Sans L', sans-serif; font-size: 10px; line-height: 11px;"></span><br />
<br />
<li style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-size: 13px; font-style: inherit; font-weight: inherit; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><br />
<div style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 10px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 8px; padding-top: 0px; vertical-align: baseline;"><span style="font-size: medium;">Peter Svensson - State of the code (+some Dojo layout goodness)</span><br />
</div><br />
</li><br />
<br />
<br />
<br />
<li style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><br />
<div style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 10px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 8px; padding-top: 0px; vertical-align: baseline;"><span style="font-size: medium;">Ingemar Resare - Google Apps use cases.</span><br />
</div><br />
</li><br />
<br />
<br />
<br />
<li style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><span style="font-size: medium;">Peter Sönnergren - App Engine + Java</span></li><br />
<br />
<br />
<br />
<li style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><span style="font-size: medium;">Johan Burell - Google Go (+ Android Cntrllr)</span></li><br />
<br />
<br />
<br />
<li style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><span style="font-size: medium;">Leonard Axelsson - App Engine + Groovy</span></li><br />
<br />
<br />
<br />
See you guys then, and a Merry Spaghettimas to you all!<br />
Cheers,<br />
PSScript Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0tag:blogger.com,1999:blog-7919361321436933137.post-83109210014074160642009-12-09T09:25:00.000-08:002009-12-09T09:25:59.544-08:00Full BrightonAnd actually, this blog *should* be about how to avoid common pitfalls when using Dojo widgets inside hidden ContentPanes (as when using Stack- or TabContainers), but I have a huge queue of, oh, two or so posts to go before that.<br />
<br />
Todays topic is of course the unreasonably nice JavaScript conference in Brighton recently - Full Frontal.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidh7Qk6iZYzIZP6NnywULa_Dk6Nb8d1YytA_5eDBjmYIjkbKzlcRPhaP4iTfjx-CvIjI5p22PxxQTSJ0KwGkwH6aabEKr9l81SrIwuIAgbT7fFJQAlK0b3g1HElHXpAzNU8f9coRIrwAzi/s1600-h/IMAG0077.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidh7Qk6iZYzIZP6NnywULa_Dk6Nb8d1YytA_5eDBjmYIjkbKzlcRPhaP4iTfjx-CvIjI5p22PxxQTSJ0KwGkwH6aabEKr9l81SrIwuIAgbT7fFJQAlK0b3g1HElHXpAzNU8f9coRIrwAzi/s320/IMAG0077.jpg" /></a><br />
</div>I have never been to Brighton before, and one of the experience was walking about the city itself.<br />
<br />
Which despite the pedestrian nature of above statement is not particularly easy, even if it's nice (sharing properties with several other activities I could think of..).<br />
<br />
The reason for the lack of simplicity is that the city is actually at least two cities, which don't like each other very much and have crashed into one another in a desperate struggle to the very end, throwing streets and towers as you please, leaving the unwary resident in crossing with no less than three busy streets, often multiples of that, where two or more have steel railings to avoid being crossed in reasonable manners.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_Eu5mF_6zI1LtmdZgWG_EnnFLgBBnBpQ_msQKCx8lDvx0WY4AkwtzyHq5znvJrus5uOx7Gm01c_HNw8DTH9q6JLF7JbP2vI_ZtkYovacVEt_MFkTXC68CGxbt95UvwwtlQU5Z-l4cY0wR/s1600-h/IMAG0079.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_Eu5mF_6zI1LtmdZgWG_EnnFLgBBnBpQ_msQKCx8lDvx0WY4AkwtzyHq5znvJrus5uOx7Gm01c_HNw8DTH9q6JLF7JbP2vI_ZtkYovacVEt_MFkTXC68CGxbt95UvwwtlQU5Z-l4cY0wR/s320/IMAG0079.jpg" /></a><br />
</div><br />
I had managed to hitch a ride out of the airport with @icaaq, or actually @icaaq's cousin, who was living with her family in Brighton since years back. After a quick freshening up in the Hotel room I managed to get to something I believe is the west end of Brighton which is chock-full of pubs, of which me and a motley crew of web developers, media folks, CEOs, CSS gurus and JavaScript madmen went to at least three (or so they say).<br />
<br />
The evening was punctuated by Christian Heilman was nice enough to lead the way to the actual beach (at 2am) to see a work of art of some sort, where I managed to take a photo of him and Lieke Arendts of Ajax.org and Javelin fame (uppermost above).<br />
<br />
The conference was set in a beautiful fin-de-last-but-last-again-ciecle cinema named Duke of York Cinema. You know what? All conferences should be in cinemas. Problem with ventilation? Nope. Too hot or cold? No way. A cinema is made for large number of people sitting for a long time looking at whatever's up on the stage. Perfect!<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ_UscZvfG3wpZ836ATa9iuvo01yMH9aRfHqrLnk-HXzxbRIdHh7BtwoD9m0B50xsLjNeBm6v_iFXJ9ADisZ8oiIKqR4X-TKXYFFDqQjbQlmpNJfZ8weNkjJ7YysPLB3uC93n1b7IDUlMF/s1600-h/IMAG0088.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ_UscZvfG3wpZ836ATa9iuvo01yMH9aRfHqrLnk-HXzxbRIdHh7BtwoD9m0B50xsLjNeBm6v_iFXJ9ADisZ8oiIKqR4X-TKXYFFDqQjbQlmpNJfZ8weNkjJ7YysPLB3uC93n1b7IDUlMF/s320/IMAG0088.jpg" /></a><br />
</div>And was it great! One of the best things was that I wasn't even speaking. I had no last-minutes slides to perfect, no slow parts of my talk to worry about - nothing. I could just sit down and enjoy the show.<br />
<br />
But even though JSConf.eu wins due to the sheer amount of good content, Full Frontal still manage to out-wattage JSConf.eu on the mere fact that it was *so* right in just one day, managing by luck or engineering to get almost every speaker not only be the right kind but sort of building upon each others talks.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb2cLGTL9tcX9bIt74Z1b8muM-TCLuQ-IIQkxPCsLyL8uYEGhjtCtmv4B0x5NFwcyHdKzN_EJsEFO-95HUUpZcyPBlue3NCFrjrqQ3lC49fXmAkIOqcUV80wVAywphkhNYWqIsL3URi-dQ/s1600-h/IMAG0091.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb2cLGTL9tcX9bIt74Z1b8muM-TCLuQ-IIQkxPCsLyL8uYEGhjtCtmv4B0x5NFwcyHdKzN_EJsEFO-95HUUpZcyPBlue3NCFrjrqQ3lC49fXmAkIOqcUV80wVAywphkhNYWqIsL3URi-dQ/s320/IMAG0091.jpg" /></a><br />
</div>Everything was good, but the absolute highlights for me was Jake Archibalds talk on JavaScript optimization. Not only for the hard data on what to do and not to do - between different browser, but he had a stunning presentation technique. First of all his slides were top-notch (can he possible be that skilled? Or do he have some secret connections in the Beeb's media departments?), and secondly he had a comic timing that made his talk the most fun-packed of the day.<br />
<br />
He had this slide of a He-man doll, which he referred to as the power of the JavaScript VMs of the moderns browsers , but crossed with terminator (next slides showing he-man with Borg eye), and a crustacean forming a battlecrab! (bext slides showing a cyborged he-man doll with a large crab-like derierre), and so on. I don't make him credit, but it was really great.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkbl_ru-FssNXei6eAZizJVCvQP26WiUJALX5S8hwuJc6OVL1IMS6YqgimvYlB4Wrr_t8yktUmGoD2DBEsfFfJcER6WQ8hQFYMQ8GuaYp6M6mi1QzAxFvHQKeS8OJ7o3ey9i-2r0jGLrDx/s1600-h/IMAG0111.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkbl_ru-FssNXei6eAZizJVCvQP26WiUJALX5S8hwuJc6OVL1IMS6YqgimvYlB4Wrr_t8yktUmGoD2DBEsfFfJcER6WQ8hQFYMQ8GuaYp6M6mi1QzAxFvHQKeS8OJ7o3ey9i-2r0jGLrDx/s320/IMAG0111.jpg" /></a><br />
</div>The next best part was the closing act, where Simon Willison had ditched his prepared talk (something about web APIs) after seeing the presentations on JSConf the week earlier, and promptly slammed together his own talk on node.js, using fluffy rabbits, cute hamsters and octopuses (OK, just one octpus), to describe the difference between threaded event handling and event-callbacks.<br />
<br />
The talk had just the same effect on Full Frontal. people whooped and became generally agitated about the idea to use their front-end kung-fu to start building heavy-hitting serve-side stuff as well. No new idea (and the Javelin guys were quietly commenting on their own KLOCs of C++ to make their own SSJS platform one of the speediest, doing essentially the same - and more), but the magic bullet here is one of perceived complexity; Noone in the room thought that they would have a hard time picking up node.js and try something out with it. Just as with CouchDB, it simple to explain and simple to use. Well, OK, I'll shut up about it for now, but expect me to be back on the topic!<br />
<br />
Anyhoo.. the after-party was nice, full of back-clapping and camaraderie,and just the right size too. I think that the superpower of the current JavaScript movement that's building is twofold; people are super-amateurish and quirky, and also nice. Really, really nice.<br />
<br />
Amateurism in really bright people means playfulness and a lowering of barriers, so that using hamsters for request is seen as OK - not very academical, but fun and getting the point across.<br />
<br />
I'll definitely be back next year (there too :)<br />
<br />
Cheers,<br />
PSScript Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com2tag:blogger.com,1999:blog-7919361321436933137.post-37812794579325402832009-12-01T10:17:00.000-08:002009-12-01T10:19:29.315-08:00GTUG Android Hackathon 28/11 2009Earlier this year, I had an idea for an all-day event for hacking on some Google technology. When I proposed this to the group at a GTUG meeting, I was reasonably certain that Wave was going to be chosen as the technology in question, and to my surprise instead Android took home most of the votes.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW8-upUcGv1sihwH7Up_8Zh46IiS2pJxcQ3OEoT41my_UZvGB6E5Dq8Ya-aVnKoJGtqSaTR6b7rzkDfwmG_Onv78o4AwC1V3dSIRDSmsAYHgltgaxOjKjVrt-ApwAjekUDKFyJHHfbc7i6/s1600/IMAG0123.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW8-upUcGv1sihwH7Up_8Zh46IiS2pJxcQ3OEoT41my_UZvGB6E5Dq8Ya-aVnKoJGtqSaTR6b7rzkDfwmG_Onv78o4AwC1V3dSIRDSmsAYHgltgaxOjKjVrt-ApwAjekUDKFyJHHfbc7i6/s320/IMAG0123.jpg" /></a><br />
</div><br />
So, Android it was. No worries, though, as I'm a great friend of the platform - even though it is still officially restricted to Google's brand of Java, but more of that this Thursday when<a href="http://sites.google.com/site/stockholmgtug/agenda_mote_3_12"> Mikael Kindborg will do a talk on JavaScript on the Android</a>, among other talks (including Sony Ericsson's Strategy Manager Thomas Bailey).<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikqZVAlkaDb_39JTvo7bxcFJXPLk8cUWXRa2GzB8hK5-ptDMcwghusZ4myKXfPIRc3jXYAi6y0Zr-VU37BYPpAaXiLuRqf2FoXePvKocg3UFxjZwTIUl3ijkZMxCczag1HYCZG37Wh6IoX/s1600/IMAG0126.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikqZVAlkaDb_39JTvo7bxcFJXPLk8cUWXRa2GzB8hK5-ptDMcwghusZ4myKXfPIRc3jXYAi6y0Zr-VU37BYPpAaXiLuRqf2FoXePvKocg3UFxjZwTIUl3ijkZMxCczag1HYCZG37Wh6IoX/s320/IMAG0126.jpg" /></a><br />
</div>The process running up to the Hackathon was almost Kafkanesque in nature. Not at the beginning, where Bwin Games agreed to host the Hackathon (on a Saturday) at their lavish premises in central Stockholm. Later, when it was apparent that the budget was rather tight at Q4 (in (yet another) year of recession) to provide dinner - something I felt was a necessity for an event stretching from 9.00am to 8.00pm.<br />
<br />
After getting literally dozens of great leads after I reached out to the community, on twitter (I'm @psvensson) and beyond, I had as many as four different companies that tried to find resources within their organizations to no avail (but thanks for the effort nonetheless!). Finally I got a possible sponsor, but then it turned out that sponsorship is a sensitive issue and the company in question had agendas parallell to that of Bwin for providing the venue in the first place.<br />
<br />
With only days left, I had to call in the cavalry and use my contacts at Google (Thanks Serge and Stephanie!) who agreed to take the bill for the dinner.<br />
<br />
What? You want to know about the Hackathon and not my orgnaizational ramblings? Why didn't you say so? Here goes:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy331EeZyVaWDGOK7FnQMt3qp4iAAWlHgBjCGeNnuRK7XndPgq3hYIe9ZlFqAW2pcI04cTyuOtIro-0IpmX1FdkuiYlqKpzJ5zEd5d-aqtFtbzfIMG3SHrJWc9jPHfR7GMpaO9xnBu6uh3/s1600/IMAG0128.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy331EeZyVaWDGOK7FnQMt3qp4iAAWlHgBjCGeNnuRK7XndPgq3hYIe9ZlFqAW2pcI04cTyuOtIro-0IpmX1FdkuiYlqKpzJ5zEd5d-aqtFtbzfIMG3SHrJWc9jPHfR7GMpaO9xnBu6uh3/s320/IMAG0128.jpg" /></a><br />
</div>As many as 49 people had signed up for the Hackathon, 43 on LinkedIn and 6 by direct email, and after all was said and done 33 showed up, but what a group. We got people from Plusfoursix, Isotop, everbody from Appcorn (who had attended whole day iPhone developer event the day before), HiQ, COMBOL and many others.<br />
<br />
Several people came just to see Dirk Groten, CTO from the progressive Augmented Reality company <a href="http://layar.com/">Layar</a>, who had graciously agreed to come up to Stockholm and demonstrate how to build service and applicaitons with their system. Layar is just at the time of this writing about to reveal their new polygonal 3D service, which lets developers created fairly complex polygons at specific geographical locations, which ups the ante a bit.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0-XUH5jbVRHFekpYfRnAjjD67DGJsKT0uriI5r5QyKMFR3eoMRdLrb66GGue5rkt00nkNVzEGrMn9hVzt5csArmzf4WjEOu-tdGhyeHzurZvD4XpJIkvcNvFz_-6nsNuSk2csPuDRGpoi/s1600/IMAG0129.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0-XUH5jbVRHFekpYfRnAjjD67DGJsKT0uriI5r5QyKMFR3eoMRdLrb66GGue5rkt00nkNVzEGrMn9hVzt5csArmzf4WjEOu-tdGhyeHzurZvD4XpJIkvcNvFz_-6nsNuSk2csPuDRGpoi/s320/IMAG0129.jpg" /></a><br />
</div><br />
After Dirk, we had a talk from our own Johan Burell, who had a thorough walk-through of the <a href="http://code.google.com/p/rokon/">Rokon</a> gaming library for Android, which provides a lot of simplifying wrappers for 2D gaming, which several of the groups later used.<br />
<br />
After the talks were done, we had a light but satisfying wraps-based lunch provided by Bwin and then on to coding.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRG9EFg7onqBVkIPU9FDobXZEC4yjz7C_y6uvbxrnuGcQfw8Wb-BYB6QEqLrQE0SLj-fBqAvipD7WZZI2-QZa9O4q6VLfJTKJUuw8hKe_lYopDqp3a5qvyuJXl_oElE_xqYqa-xfZ2_225/s1600/IMAG0130.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRG9EFg7onqBVkIPU9FDobXZEC4yjz7C_y6uvbxrnuGcQfw8Wb-BYB6QEqLrQE0SLj-fBqAvipD7WZZI2-QZa9O4q6VLfJTKJUuw8hKe_lYopDqp3a5qvyuJXl_oElE_xqYqa-xfZ2_225/s320/IMAG0130.jpg" /></a><br />
</div><br />
<br />
The atmosphere during the whole day was very open and friendly. Teams helped each other out on several occasions, fixing solutions to MapView dynamic updating to getting the current GPS position.<br />
<br />
Also, there was (at least I had quite a few :) a lot of general discussions on and off, about whether it was amoral for Craigslist to provide free advertising, thus putting newspapers out of business, the recent split of the <a href="http://www.squeak.org/">Squeak</a> Smalltalk platform into <a href="http://www.pharo-project.org/home">Pharo</a>, CouchDb REST musings and lots of other stuff.<br />
<br />
What I mean to say is that these coders weren't your garden variety lockergnomes, these were hard people, OK? just saying :)<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK2XIaX1idfwEGp6tDyjJLEafPGhfVPDFzb5KGXqQCXuwnh_nn6l6MWxYgdpQD7_9sPaGsDsDtOHkz4EPiP8N-_LnHYsl5cRquaM5ZvbVFR1Z_ebIZdfGWsqJ0UzWSfRqRZ3j4SsuecJL_/s1600/IMAG0141.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK2XIaX1idfwEGp6tDyjJLEafPGhfVPDFzb5KGXqQCXuwnh_nn6l6MWxYgdpQD7_9sPaGsDsDtOHkz4EPiP8N-_LnHYsl5cRquaM5ZvbVFR1Z_ebIZdfGWsqJ0UzWSfRqRZ3j4SsuecJL_/s320/IMAG0141.jpg" /></a><br />
</div><br />
Some teams borrowed meeting rooms from Bwin to doodle on white boards, but most teams huddled down in groups, hacking intently as the dusk fell over Stockholm. Actually, dusk was all we had that day, steel-blue clouds and a mere thirty seconds or so of sun.<br />
<br />
At the end of the day, each time got one minute - sometimes a verrry long minute - to present their application. After everyone had presented, everybody present (some people had to leave before the presentations) voted by raising their hands (only one vote per person) on the app they liked best - and one was not allowed to vote for ones own. As it turned out first price went to the Bwin team with their app "Crimesweeper", which got real-time police crime scene data, and mashed it up in a MapView, awarding points for players who visited the scene (vigilante.apk?)<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNF51vC-RnRpqG-J8tHR1EawFgrU7zm9dPXBz_jnWVDZ-6dKZZBbCA9hgNc5VbVl72KpaMUyomswywiCw4fJIVvTGaMrLShwcbmwXyWnXSOT6O0y0uRz5Sl5Xh8p23scMjVch4PUd69O2l/s1600/IMAG0145.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNF51vC-RnRpqG-J8tHR1EawFgrU7zm9dPXBz_jnWVDZ-6dKZZBbCA9hgNc5VbVl72KpaMUyomswywiCw4fJIVvTGaMrLShwcbmwXyWnXSOT6O0y0uRz5Sl5Xh8p23scMjVch4PUd69O2l/s320/IMAG0145.jpg" /></a><br />
</div>The second-price winners had made a very creative game app which tracked the players and plotted them on each others screens, and provided a method for throwing virtual water baloons at each other.<br />
<br />
Then one team had made a very useful Hudson front-end for Android where you could start Java build jobs and check their statuses.<br />
<br />
One team had made almost a space shooter with the Rokon library, but due to time constraints it was actually a "space dodger" - tasteful nonetheless.<br />
There was an app which demonstrated a CouchDB library for the Android, something really useful.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio76DWoFAdHpR5FMfhBxyD7uWiYFu27okrcbP_wVqvsB1CXP7OSr022-xOQ6T7lapOwf9BY_qKaJbuYXG9nw0p_StHmMn10o4vz4bIEiu7OHbbQ_UzmivQNAhbkrejlVRaNYSm8h5yEwsD/s1600/IMAG0146.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio76DWoFAdHpR5FMfhBxyD7uWiYFu27okrcbP_wVqvsB1CXP7OSr022-xOQ6T7lapOwf9BY_qKaJbuYXG9nw0p_StHmMn10o4vz4bIEiu7OHbbQ_UzmivQNAhbkrejlVRaNYSm8h5yEwsD/s320/IMAG0146.jpg" /></a><br />
</div>One app which was made by an attendee who was forced to leave before the voting (please comment if you remember who - thx!) made an app for kids learning words using images and rotating letters - which was very appreciated, but got few votes. Strange, but what do you do? :)<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCUDZb7XpwmBrJJDimAHM3H1SA0LGycBTofuKgY_decphyQfQDgb2rdceWzlsqC10GXK_LKjqPUr7lbrQuoTjYdhErvhMWYJjesXdXfAzLepND54i7U5v3TPZlqsUpowx5AuBy3qUyOg9Z/s1600/IMAG0147.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCUDZb7XpwmBrJJDimAHM3H1SA0LGycBTofuKgY_decphyQfQDgb2rdceWzlsqC10GXK_LKjqPUr7lbrQuoTjYdhErvhMWYJjesXdXfAzLepND54i7U5v3TPZlqsUpowx5AuBy3qUyOg9Z/s320/IMAG0147.jpg" /></a><br />
</div>We had another app by single-team @sharj, which used the twitter API to get a random twitter user bio and let you follow if you liked it. In the future he means to add support for recommending users based on usage patterns.<br />
<br />
And he got another one as well, which used the recent Google Movies API to list movies and to say which ones you were going to see, foursquare-style, of sorts.<br />
<br />
@burre83's team made a rhythm-action app, which was surprisingly catchy, tempting the player to hit random parts of the screen in time to the music.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXmgm7khCTN5MCTacaavLmypQEabcHNHzQiV6AL_nXf2E-b1wiAsWDzLg5JTn10dyIeicq9GwbDimeUOMiipqeCMurcwr45YduKsnoxjR6WwB9xH9HV7SzVneCb80AIN57z6-cLjFPklF4/s1600/IMAG0150.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXmgm7khCTN5MCTacaavLmypQEabcHNHzQiV6AL_nXf2E-b1wiAsWDzLg5JTn10dyIeicq9GwbDimeUOMiipqeCMurcwr45YduKsnoxjR6WwB9xH9HV7SzVneCb80AIN57z6-cLjFPklF4/s320/IMAG0150.jpg" /></a><br />
</div><br />
A couple of teams did not finish, but a couple came surprisingly far, given their ambitions.<br />
<br />
What was interesting was that so many teams had such divergent ideas, and that so many attendees came without really any prior Android development experience - and still managed to produce runnable code!<br />
<br />
The winners and the second place teams got each a book from Apress called "Pro Android" which in my opinion is the most comprehensive one out there. The winning team also got some really nice Google drinking bottles and my very last Android keyring trinkets,which were much appreciated.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoOtSkC8JVvcvAP-OhTzZoKVpqMHChoSTN3T6vDaEgMY8xeF9ebUi2PZ2y7kvMiZWm0SxzokSjsbXtD7kEBk6o22TjOrFL71_vJJ19lIxGWkjIk0NQhF44LIl9sL685X_q8y8cNlF3J-0x/s1600/IMAG0153.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoOtSkC8JVvcvAP-OhTzZoKVpqMHChoSTN3T6vDaEgMY8xeF9ebUi2PZ2y7kvMiZWm0SxzokSjsbXtD7kEBk6o22TjOrFL71_vJJ19lIxGWkjIk0NQhF44LIl9sL685X_q8y8cNlF3J-0x/s320/IMAG0153.jpg" /></a><br />
</div><br />
This left me with a couple of books left (since Apress had sent me 10), which after due consideration was given to to teams which I felt needed them the most, for different reasons.:)<br />
<br />
When everything was wrapping up, we decided to go down to the local pub Bishops Arms at Vasagatan for some beers and lots of discussion - some about Psytrance and scouting if I recall correctly.<br />
<br />
In retrospect the day went very smooth, mostyl due to the playful professionalism of all present. Also, since most of the day was spent by the attendees hacking I had several hours on and off where I could blog about my adventures in Russia and other events that needed some writing.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Dfnrtj-dVOTu9fCwtltbE5vvjus4WEx8RkmJvwnP_Oh3IGbbuSB5qO815SRuqj1GospmmjEHdOY0pGCqEyQVzxmFu2e0cwV1e5TK10BxMbOj0GAy7ct8IHB2MAw1ETdVKHupBJM8FKTZ/s1600/IMAG0156.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Dfnrtj-dVOTu9fCwtltbE5vvjus4WEx8RkmJvwnP_Oh3IGbbuSB5qO815SRuqj1GospmmjEHdOY0pGCqEyQVzxmFu2e0cwV1e5TK10BxMbOj0GAy7ct8IHB2MAw1ETdVKHupBJM8FKTZ/s320/IMAG0156.jpg" /></a><br />
</div><br />
This had been hanging over me for some time, and it felt really good to be in a position to do something about it, between coaching sessions and general discussions.<br />
<br />
Something that really meant a lot to me was that three separate people, on separate occasions, went up to me and said how great they thought the event was and thanked me for arranging it. Me, who really didn't do much in particular, other than yakking and blogging :)<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Q2QpnnwPvlf0WQ7wzAO8jdkca5FLMnqomGe_kNZh_8IlevP0qv7A1jVrOYV-sjFa6yW4-LwZUR9EMzGmzvDyZornAFeRPilDYVCkvo-dnWloM2UiL_2FvzfIxNhL2OFbjIyvDRtSYORT/s1600/IMAG0162.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Q2QpnnwPvlf0WQ7wzAO8jdkca5FLMnqomGe_kNZh_8IlevP0qv7A1jVrOYV-sjFa6yW4-LwZUR9EMzGmzvDyZornAFeRPilDYVCkvo-dnWloM2UiL_2FvzfIxNhL2OFbjIyvDRtSYORT/s320/IMAG0162.jpg" /></a><br />
</div><br />
Thank you so much! ^-^Script Unclehttp://www.blogger.com/profile/16751089093335901438noreply@blogger.com0