I will be giving a talk on Microsoft Windows Azure on the 22nd of September at Microsoft’s Danish headquarters in Hellerup.
Attendance is free of charge, so sign up and get ready for a tour through the Cloud!
I will be giving a talk on Microsoft Windows Azure on the 22nd of September at Microsoft’s Danish headquarters in Hellerup.
Attendance is free of charge, so sign up and get ready for a tour through the Cloud!
Microsoft recently released the “Web Application Toolkit for Freemium Applications” for building applications based on the freemium model. I am not a big fan of the Freemium model myself, but I thought it would be interesting to take a closer look at the toolkit anyway.
First off, let’s recap the freemium model. According to Wikipedia:
Freemium is a business model that works by offering basic Web services, or a basic downloadable digital product, for free, while charging a premium for advanced or special features.
Thus, to build applications for the freemium model, we need to be able to
It might also be nice to
This is what the toolkit should ideally help us achieve.
In broad terms, the toolkit works on two concepts: features and SKUs, and it uses the ASP.NET Membership functionality to associate users to SKUs. SKUs are sets of features and each SKU has a unique identifier called a slug. SKUs are mapped to users by means of standard ASP.NET Roles having the same name as a SKU slug. Thus, there will be a “Gold” SKU identified by the slug “gold” and all users in the role “gold” are associated to the Gold SKU.
If you buy into this way of grouping features and associating them with users, the framework provides:
The components described in the three bullets above are definitely valuable in any application based on the freemium model. However, their actual implementation leaves something to be desired. The provided functionality isn’t componentized properly and there is a general lack of extension points: to really use the toolkit, you need to buy into a lot of arbitrary design decisions which are unlikely to suit your application. Moreover, there is just a gust of code smell around it: views aren’t properly decoupled from business logic, no DI is used etc.
All in all the Web Application Toolkit for Freemium Applications is a nice initiative from Microsoft and it contains some relevant thoughts. If Microsoft decides to put some effort into the toolkit to provide extension points etc., it may even be able to kickstart your next freemium application. At the moment, however, the toolkit is pretty blunt. It is nothing more than a sample implementation which may provide inspiration but does not deserve to be called a toolkit.
The Web Application Toolkit for Freemium Applications is available on MSDN.
I was recently searching for a SaaS offering for email management and stumbled upon a product that looked interesting.
The provider’s website frontpage is pretty decent. It presents three main gateways if you want to learn more about the product and its benefits:
I really like the idea of using online videos to present a SaaS product. If you ask me to use 15 minutes to concentrate my thoughts and strain my eyes to read your product presentation, I will consider it. If you ask me to invest 15 minutes in watching a video, I will be happy to kick back and enjoy the show. A video presentation available online 24/7 is a great approach for many SaaS companies.
Thus, I clicked the “Take the video tour here” button and chose the first video from a list. To access the videos, you then need to sign up in the guestbook:
“So, just to get to see a set of videos introducing your service, I have to fill in all those fields? And you’ve even added aggressive, red asterisks to the majority of the fields, indicating that they are required and depriving me of any hope that you might let me off easy? Hmmm, I wonder if someone has tweeted anything interesting?”.
The point is: the service provider doesn’t need this information just to show me some videos, so they shouldn’t ask for it! And certainly not require it!
As I mentioned in my previous post, every step the prospect has to take to become a paying customer, is a potential barrier to entry. In this case, the provider has lost me before I even know if their product is fantastic. Once I have checked Twitter, put on another kettle for coffee and gotten back to the computer, I will fire up a new browser, hit Google and restart the search.
Only require information from the user when it is necessary. If you need information like company name etc. to set up a test account, provide defaults. If some piece of information is only required when using a particular feature of your application, only ask for the information when that feature is first used.
When delivering a SaaS offering two factors are crucial to profitability
You obviously want a large customer volume and a low CAC. To this end you will typically employ the power of viral marketing and cheap and scalable online marketing. Hence, you will not have sales people in the field actively herding customers through the sales funnel. Instead, your online initiatives and community need to be able to turn leads into customers autonomously. Actually, the sales cycle is not a sales funnel as much as it is a sales vacuum hose. Customers have to be sucked into your business. Since no-one is around to actively respond to prospects’ whims and wishes and since prospects have a free will (gasp!), the slightest barrier to entry in your sign-up process can have a large impact on your customer volume.
If you read up on some of the lore on designing a webshop and its checkout process, you will see that a lot of energy is put into streamlining the buying process. At every step of the process, a webshop risks loosing customers if they can’t figure out where to go next or if they are just distracted.
When selling SaaS, streamlining the process from initial interest until you can charge the customer is even more important and even harder to get right. SaaS vendors usually offer the option of trying the product for a period of time before buying. This means that there is ample room for something to trip the customer up.
The process of getting someone to sign up for your service looks something like this:
Each step in the process is a possible barrier to entry, so you have to think very carefully about each step. Heed the advice of webshop designers, e-commerce consultants and usability gurus, but keep in mind that turning a prospect into a paying SaaS customer is a much more complicated process than making a customer go from A to B in a webshop.
When designing your sales cycle, you should keep the 5 steps above in mind and actively seek to make the transistion between each step as effortless as possible.
I recently read this post on meta.stackoverflow.com on monitoring your SO status using Python. Since I’ve been looking into Pyhon (IronPython in particular) lately, I figured it might be fun to try the provided script out in IronPython.
I quickly experienced some problems pertaining to the sqlite3 and urllib2 modules which I was unable to solve, so I downloaded and installed Python 3.1 for Windows.
The original script does not run against Python 3.1 because of some string encoding issues. Moreover, the regular expressions used in the original script no longer match the markup of SO, so I have updated the script somewhat:
questLen = 60 #digits before elipses kick in
connection = sqlite.connect(“C:\\Users\\Rune Ibsen\\Projects\\SO\\profile.db”)
cursor = connection.cursor()
user = #your user id
request = urllib2.Request(url = ‘<http://stackoverflow.com/users/%i/myProfile.html>’ % (user))
profile = urllib2.urlopen(request).read()
profile = profile.decode(“utf-8″)
rep = re.compile(’summarycount”>.*?([,\d]+)</div>.*?Reputation’, re.S).search(profile).group(1)
rep = rep.replace(‘,’,”)
badge = re.compile(‘<’+‘div class=”summarycount ar”.{0,50}>(\d+).{1,100}Badges’, re.S).search(profile).group(1)
stQuestion = re.compile(‘Questions</h.*?Answers</h’, re.S).search(profile).group()
mQuestion = re.compile(‘question-summary narrow.*?id=”question-summary-(\d+)”.*?class=”votes”.*?(\d+).*?class=”status.+?(\d+).*?<h3><a.+?>(.+?)</a>’, re.S).findall(stQuestion)
# mQuestion contains tuples containing (id, votes, answers, title)
stAnswer = re.compile(‘<h1>Answers</h1>.*?<script’, re.S).search(profile).group()
mAnswer = re.compile(‘answer-summary”><a href=”/questions/(\d*).*?votes.*?>(-?\d+).*?href.*?>(.*?)<.a’, re.S).findall(stAnswer)
stTime = time.strftime(“%Y-%m-%d %H:%M:%S”)
print (stTime)
print (‘\nQuestions (‘ + str(len(mQuestion)) + ‘):’ )
for quest in mQuestion:
cursor.execute(‘SELECT count(id), votes FROM Questions WHERE id = ’ + quest[0] + ‘ AND type=0;’)
item = cursor.fetchone()
if item[0] > 0:
lastQ = (int(quest[1]) - item[1])
if lastQ==0:lastQ=“”
cursor.execute(‘UPDATE Questions SET votes = %s WHERE id = %s AND type = 0′ % (quest[1], quest[0]))
else:
cursor.execute(‘INSERT INTO Questions VALUES(“‘+quest[3]+‘”,’+quest[1]+‘,0,’+quest[0]+‘);’)
lastQ = “(NEW)”
if len(quest[2]) > questLen:
elips=“…” #in case the question is really long
nElips = 0
else:
elips=“”
nElips = 3
print (‘%s%s %s%s’ % (quest[3][:questLen].ljust(questLen+nElips,” ”),elips, (“(“+str(quest[1])+“)”).ljust(5,” ”), lastQ))
print (“\nAnswers (“ + str(len(mAnswer)) + ‘):’)
for answer in mAnswer:
aId = answer[0]
aVotes = answer[1]
aQuestion = answer[2]
cursor.execute(‘SELECT count(id), votes FROM Questions WHERE id = ’ + aId + ‘ AND type=1;’)
item = cursor.fetchone()
if item[0] > 0:
lastQ = int(aVotes) - item[1]
if lastQ==0:lastQ=“”
cursor.execute(‘UPDATE Questions SET votes = %s WHERE id = %s AND type = 1′ % (aVotes, aId))
else:
cursor.execute(‘INSERT INTO Questions VALUES(“‘+aQuestion+‘”,’+aVotes+‘,1,’+aId+‘);’)
lastQ = “(NEW)”
if len(aQuestion) > questLen:
elips=“…”
nElips = 0
else:
elips=“”
nElips = 3
print (‘%s%s %s%s’ % (aQuestion[:questLen].ljust(questLen+nElips,” ”),elips, (“(“+str(aVotes)+“)”).ljust(5,” ”), lastQ))
cursor.execute(‘SELECT rep, badges, questions, answers , COUNT(date) FROM profile WHERE user = ’ + str(user) + ‘ ORDER BY date DESC;’)
oldData = cursor.fetchone()
if oldData[4] == 0:
oldData = [0,0,0,0]
cursor.execute(“INSERT INTO profile VALUES(%s,%s,%s,%s,’%s’,%i);” % (rep,badge,len(mQuestion),len(mAnswer),stTime, user) )
print (‘\n‘)
print (‘%s Questions, %s new’ % (len(mQuestion),(len(mQuestion) - oldData[2])))
print (‘%s Answers, %s new’ % (len(mAnswer),(len(mAnswer) - oldData[3])))
print (‘%s Reputation (%+i)’ % (rep, (int(rep) - oldData[0])))
print (‘%s Badges, %s new’ % (badge, (int(badge) - oldData[1])))
connection.commit()
Note that
Running the script will result in something like this:
When developing an application targeted for Windows Azure, your application will be executing in an environment to which you have somewhat limited access, making debugging hard. Thus, you will probably want to test your application as much as possible before deploying it. Enter unit testing.
To be able to execute unit tests against the Azure storage (well, maybe such tests are more like integration tests), you need to have the Azure Development Storage running when the tests are executed. To achieve this, you will need to do two things:
The first task is taken care of by installing the Windows Azure SDK. If you are developing Windows Azure applications, you will probably already have this installed on your computer. However, if you plan to run your tests on a dedicated build server, you may need to install the SDK on that machine.
For the second task, you need to start the Development Storage prior to executing tests. To start the Development Storage you can use the CSRun utility from the Azure SDK. If you have installed the SDK to the default position, you will find csrun.exe in C:\Program Files\Windows Azure SDK\v1.0\bin:
If you want to integrate this task with your build scripts, you can of course create a NAnt target for it:
<property name="azure.sdk.csrun.exe" value="C:\Program Files\Windows Azure SDK\v1.0\bin\csrun.exe"/> <target name="azure.devstorage.start" description="Starts the Azure Development Storage"> <exec program="${azure.sdk.csrun.exe}" commandline="/devstore:start"> </exec> <sleep seconds="5"/><!-- Sleep 5 seconds, waiting for the development storage to start --> </target>
As you can see, I have added a delay in order to allow the storage to fully start before subsequent tasks are executed.
Now just call this target before executing your unit tests. You may also want to shut down the Development Storage upon completion of your tests. Use csrun /devstore:shutdown to do this
Note that if your project is the first project to use Development Storage on the build server, you will want to initialize the database underlying Development Storage before running tests. Initializing the Development Storage will create a database called something like DevelopmentStorageDb20090919 in the local SQL Server (Express) instance.
You just need to do this once. However, if you feel like it, you can force DSInit to recreate the database as part of your test procedure by issuing the command dsinit.exe /forceCreate. DSInit requires administrator privileges, though.
I am not entirely satisfied with the result that WP LaTex produces. Obviously, the white background on every little piece of math is a problem. Moreover, it only supports the simplest of layouts – at least I can’t get environments like displaymath, align etc. to work properly. Therefore, I decided to look into MathML. MathML is a W3 Recommendation specification for describing mathematics intended for machine to machine communication. That means in particular that MathML may be used by webservers to send mathematical content to client browsers.
Thus, MathML should be able to achieve the same goal as the WP LaTeX plug-in. However, this alternative comes at a price, since it relies on the browser being able to render MathML. Alas, browser support for MathML is somewhat limited: Firefox supports MathML, but IE needs a plug-in. You would think, Google caring so much about spreading good karma, that Google’s Chrome browser would support MathML, but it doesn’t. Not in any shape or form. Since I like Chrome very much for its speed and ease of use, I find this very disappointing.
However, most of the math I am authoring is just for my personal reference, so I don’t have to adhere to browser support restrictions too much and I decided to move forward and try to find an editor capable of producing MathML (besides Notepad, obviously).
The W3 organisation has a list of MathML editors, of which I have tried a few.
This is a Firefox plug-in (much like Firebug etc.) and may be the best free option at the moment. It has a nice preview region, a reasonable layout and the generated XML is easily accesible. I will evaluate this further, before I pass my judgement.
The MathML Editor for Flash is, as the name suggests, a Flash application for editing and rendering MathML. You can try MathML Editor for Flash out here. It is pretty rudimentary and, unless I am greatly deceived, it is nigh impossible to typeset anything but the most basic expressions. The process of building an expression is very hierarchical, and you have to somewhat plan this hierarchy in advance. If you have got lots of indexes, superscripts, accents etc., you are going to have to start over again and again. Trying to typeset
drove me crazy with frustration. Also, I gave up on this application when it took me more than a few minutes to find the symbol (I never found it).
http://code.google.com/p/mathmleditor/
I’ve been working a little with an old friend, modal logic, this weekend. This digressed into a study of lattices and Boolean algebras, so I thought I would write up some of my observations for archival. Also, I just like to say “lattice”.
If you know anything about lattices, you will probably find this stuff trivial. If you don’t know anything about lattices, a free and much better introduction can be found in A Course in Universal Algebra.
Definition: A distributive lattice is a lattice which satisfies the distributive laws:
Actually, it can be shown that a lattice satisfies D1 iff it satisfies D2.
Definition: A lattice L is said to be modular if the modular law holds:
Lemma: The modular law for lattices is equivalent to the identity
Proof
Assume that the modular law holds and consider the expression . Since
we can apply the modular law to infer that
.
Now, assume that the identity holds and that for some
. Then
so
where the identity was used in . Thus, the modular law holds.
Theorem: Every distributive lattice is modular.
Proof
Assume that for some
where
is a distributive lattice. Then
so
where we have made use of D2. The desired result now follows from the lemma.
My dear aunt recently insisted that I borrow a load of novels from her, so, from a family feast, I brought home a couple of novels by authors completely foreign to me. Among these were Haruki Murakami, a japanese author and translator who, unbeknownst to me, had his international breakthrough in 1994 when he published The Wind-Up Bird Chronicle.
In later years, I have had trouble finishing novels about which I have no prior knowledge or which I have not been looking forward to reading for a long time. I usually fail to finishing a novel because something else stirs my interest, be it another novel, a math subject, a computer science subject, a new Microsoft technology etc. Most strikingly, I recently gave up on The Gormenghast Trilogy because I decided I needed to read an introductory text on archaeology. While this flaw makes me a very consistent customer with Amazon (at any time, I usually have 10 items in my basket and 25 items on my Amazon Wish List), it also means that I approach novels of the aforementioned type with some apprehension (thus probably creating a vicious circle).
Hence, when I picked up Murakami’s After Dark, which had at that point sat untouched on my bedside table for a couple of weeks, it was with some trepidation. But, my reservations were quickly put to shame; reading After Dark was like a breath of fresh air:
The setting is Tokyo after darkness. The streets are deserted. A lone girl sits at a café reading a novel. Jazz records play in the background as she passes the night sipping coffee and smoking cigarettes. At a nearby hotel, a chinese prostitute is assaulted by a customer who, after leaving the prostitute, returns to his night job as a computer programmer.
This may not seem like much of a plot, but the strength of the novel is the atmosphere which it conjures. I find it hard to put my finger on exactly why this atmosphere, one of melancholy and film noir, is so special, hence I can only encourage you to experience it for yourself. It is unlike anything else I have read.
I finished After Dark quickly and immediately did a bit of research and put The Wind-Up Bird Chronicle on my wish list for Christmas. Just before Christmas I even found it on sale, had it wrapped and put it under the tree – from me to me, just to be sure
.
Thus, I am now reading The Wind-Up Bird’s Chronicle and very much enjoying it. It has a sort of Kafkan feel to it, in that, just like Joseph K of The Trial, the main character of The Wind-Up Bird’s Chronicle seems to be the victim of causes, actions and rules of which he is mostly oblivious, but which are, at least partially, understood by the people that he meets.
I received Devils by Dostoevsky for Christmas, but I already own his collected works, so I will probably trade it for one or more novels by Murakami. Specifically, I have already set my sights on Norvegian Wood. In fact, I expect that Murakami will, in a few months, rank up there among my favourite authors along with Fyodor Dostoevsky and Umberto Eco.
So, the point is, if you haven’t experienced any of Haruki Murakami’s works, go treat yourself to a couple of his novels and a couple of days off
.
I guess the WP LaTeX server doesn’t have the xy package installed.