Upgrading to Clojure 1.3
As Nathan Marz eloquently argues, you should write even if you have no readers. So I’m starting to write again.
Here’s my notes on upgrading a fairly large project from Clojure 1.2 to 1.3.
The first step was to just change the version number and re-build. Of course, that didn’t work – I got a million warnings about dynamic variables not being explicitly declared, and eventually, there was an error complaining that I’m trying to bind a non-dynamic variable. Fair enough, the world has moved on and we weren’t looking. As most of these warnings and the error weren’t in our code, I realised that I’d have to upgrade clojure contrib as well.
Sounds simple… The problem is that, the Clojure guys have chopped it up (correctly, see Single-responsibility principle) into small bits, so you only import the ones you want. Also, many former contrib pieces are now part of Clojure core. There’s a helpful page here – http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go.
There are however many contrib libs that aren’t covered on that page, such as the unhealthy looking java-utils one. So as I’m probably going to invest a significant amount of time looking for them, I’m just going to make a note of where I found them.
The first thing worth mentioning is that as I started grepping around, it turned out many dependencies were declared but never used, or used only once, where it wasn’t really necessary and also that I found at least two whole files that I could delete completely – so this kind of exercise is always worth it, as even if it fails, you learn a lot about the code and may end up with other incidental improvements.
To begin, here’s a handy command which lists all the contrib dependencies in your project:
find . -name *clj | xargs grep contrib | grep -o "[0-9a-z\.\-]*\.contrib\.[0-9a-z\.\-]*" | sort |uniq
This page is useful too, as it shows the git repos of the new modules – http://dev.clojure.org/display/doc/Clojure+Contrib. Here’s where I found some of them:
clojure.contrib.base64 has become data.codec (Git repo: https://github.com/clojure/data.codec, Namespace: clojure.data.codec.base64, Group and artifact Id: org.clojure, data.codec, 0.1.0)
clojure.contrib.json has become data.json (Git: https://github.com/clojure/data.json, Group/artifact: org.clojure, data.json, version 0.1.2, Namespace: clojure.data.json)
clojure.contrib.except has gone – I had a couple of throw-if calls there, replaced those with assert – seems simpler.
clojure.contrib.lazy-xml -> https://github.com/clojure/data.xml, Namespace: clojure.data.xml, Group/artifact Id: org.clojure, data.xml.root., this repo isn’t ready to use yet… I figured however, that we only use one function form there, so I temporarily copied it into our code until they sort it all out.
clojure.contrib.math has become math.numeric-tower (Git: https://github.com/clojure/math.numeric-tower.git, Group/artifact Id: org.clojure/math.numeric-tower, v 0.0.1, Namespace: clojure.math.numeric-tower) – That one came with windows end-lines – funny….
Next, clojure.contrib.java-utils has gone. This post contains details – http://groups.google.com/group/clojure-dev/browse_thread/thread/b4acea9c95a9cfe9. It is a bit out of date, though, these have moved again after that. I found the best thing to do was to clone the clojure-contrib from github, checkout the 1.3.x branch and rgrep for the functions. The ones we were using from java-utils, I found in either clojure.contrib.io or clojure.contrib.string.
clojure.java.shell (and shell-out) – this is now in clojure itself, no external artifact, just require clojure.java.shell.
clojure.java.jdbc (Group/artifact: org.clojure/java.jdbc, Version: 0.1.1)
clojure.contrib.prxml – that one’s a mystery… Disappeared. I copied it from clojure-contrib into our codebase until it is available again. Noting that it’s probably wrong to use this for HTML, which isn’t strictly speaking XML.
clojure.contrib.string has gone to clojure.string – easy one.
clojure.contrib.classpath is clojure.java.classpath
str-utils, containing functions like re-split and str-join has disappeared – those functions are now largely in clojure.string – it was quite easy to change any references to those.
We had some obscure stuff being “used” – I bet every project has obsolete references remaining from either a copy/paste or things being removed/moved from a file without removing the reference. Seems that deleting code correctly is harder than writing it. And also, when you’re busy doing something like this you really appreciate the use of
(:require [x.y :as y])
over
(:use x.y)
Makes it much easier to find where that package is actually used if it is used.
clojure.contrib.zip-filter is now in clojure.data.zip (Group Id: org.clojure, Artifact Id: data.zip, Version 0.1.0, Namespace: clojure.data.zip, clojure.data.zip.xml). Note that clojure.zip is still there – that’s just zip-filter I’m talking about.
Clojure 1.3 requires dynamic defs to be explicitly indicated with ^:dynamic – that removes the warnings.
And just when I thought I was done – I wasn’t – had to upgrade Ring to 1.0.0, Compojure to 1.0.0-RC1 and Scriptjure
Next thing – the new clojure.java.shell/sh doesn’t return the command output, it returns a map, which contains the output, so I had to do (:out (sh/sh ….))
The next one was less expected, there was a clojure.lang.ILookup class, which seems to have disappeared in 1.3, I’ll just remove the type hint for the time being.
OK, there’s more – the hexadecimal literal 0x1b, is now a java.lang.Long, as opposed to java.lang.Integer in 1.2, which broke the fancy bright color console print-outs we had.
Yeay!!! It is compiling and starting up! I’m sure that other things will pop up as I go along, and I’ll try and post them. Off to do some testing…
Filed under: Uncategorized | Leave a Comment
Captured requirement
If you make software for a big organisation, you hear a lot about ‘captured requirements’. I never really saw a ‘captured requirement’, but one morning I felt a flood of compassion for these fragile and sensitive creatures that we keep chasing and capturing, so I drew a picture of a ‘captured requirement’…
Filed under: Uncategorized | Leave a Comment
Tags: requirements specification enterprise
It’s as simple as the following code. The Conditional Tail Expectation risk measure tells you how much on average you will lose if your returns are in the bottom X% quantile, based on a bootstrapped projected distribution. It is distribution agnostic – you give it the past returns and it randomly rearranges them (with replacement) to give you a number of projected returns over your required horizon. Not sure yet if the random function distorts that, because you are choosing the returns randomly, but the array indices probably are normally distributed. Can’t think about that right now, may or may not be a problem, but then it’s just a matter of getting a better random function. But I didn’t have to explain this. It is evident from the code. That’s the great thing about functional programming – it is the code, the specification, and the documentation. This took about half an hour to write, including consulting the latest Scala API. Ignoring the main(…) method, it more or less reads in English.
Note that in reality it’ll probably take you a bit more than that – a 5% CTE is useless as it means you’ll lose this much 1.5 times a month, and obvoiously there’s a lot more work in working out past returns, etc, but what I’m trying to say is, it’s way more than what some other programming languages can give you. And may be the returns shouldn’t be added but compounded, not sure about that either, but again, it illustrates the point – if I wanted to compound them, it’s just a change in the foldLeft function in sim.
package com.supplesoftware.finance.cte
object CTE {
def main(args:Array[String]):Unit =
print(calc.cte(Array(-3.0,-7,0,1.0,2.0,3.0,4.0,5.0,7.0), 10, 100))
}
package object calc {
def cte(pastMonthlyReturns:IndexedSeq[Double],
horizonInMonths:Int,
numberOfSims:Int) =
average(quantileMembers(
bootstrap(pastMonthlyReturns, horizonInMonths, numberOfSims)))
def average(distribution:Seq[Double]) =
distribution.foldLeft(0.0)(_+_/distribution.size)
def quantileMembers(distribution:IndexedSeq[Double]) =
distribution.sortWith((a,b)=>a < b).take(5)
def bootstrap(pastMonthlyReturns:IndexedSeq[Double], horizonInMonths:Int, numberOfSims:Int) =
(1 to numberOfSims).map(_=>sim(pastMonthlyReturns, horizonInMonths))
def sim(pastMonthlyReturns:IndexedSeq[Double], horizonInMonths:Int) =
(1 to horizonInMonths)
.map(_=>pastMonthlyReturns(random.nextInt(pastMonthlyReturns.size)))
.foldLeft(0.0)(_+_)
val random = new scala.util.Random
}
Filed under: Uncategorized | Leave a Comment
Why is Google pushing Chrome?
You must have noticed the adverts. Big, loud and ubiquitous. Even one at Vauxhall Bus station. I think they know what they’re doing. They want Chrome to become mainstream, because it’s not just a browser. It’s an operating system. Look at Chromium. Those who have seen applications run in a browser, now ranging from Google Docs, through Calendar, through to Doom online, know what I mean. Javascript running in a browser is now almost as good as a native app (yes, I know Doom Online is not JS). But not quite. Google docs is no MS Office. But what if you had a ridiculously quick virtual machine that could make it MS Office? That’s what Chrome wants to be.
And then it’s done, the old Sun ideal of “The network is the computer” goes live and kicking. Then you can sell a PC with a browser and nothing else. Look at Chromium.
What do you use a PC for? Browsing the web, email, social networking (browsing the web), reading and writing documents, possibly spreadsheets, if you’re a finance student, possibly games, possibly gambling and p*rn (Avenue Q fans, do the catch phrase), possibly playing music and film, possibly even TV (browsing the web?), account management, that kind of stuff. It’s all available in a browser now. Except, browsers are still no match for the native app. That’s what Chrome wants to achieve.
And it’s both fantastic and may be not so at the same time. It’s fantastic, because all the paraphernalia of yesteryear’s mass-computing, all the stuff that shoveled more money into the hands of the few in the know will be gone. Firewalls, anti-viruses, backups, DVD/CD-players and writers, office suites, everything. Just go to the right URL and you’ve got it. Fantastic, because you don’t have to go to the shop, buy a box with a DVD in it, and spend the weekend installing an troubleshooting. Want to share pictures? Open a Flickr account (or Picassa, as Google would prefer). No backups, no physical media (that you’re aware of), no wondering how to organise it, no sending DVD’s to auntie Matilda. What is it that you can’t do in a browser?
What’s more, they’ve now got Gears. Which means your processing power can be used to do stuff locally, reducing the need for more bandwidth. Now, imagine a Gears on steroids, where your computing problem (e.g. a Google Spreadsheet computation) is actually sent for execution on a number of random unsuspecting PCs that would have otherwise been idle. The network is the computer! Map-reduce will change the world. It’s not a question of how much memory, storage and processing power you have, it’s a question of how much memory, storage and computing power are currently available worldwide. A bit like electricity.
What’s possibly not so good about it? When it goes wrong, it goes wrong big time. The engineers at Google should know that. Mind you, I’m sure they do know that, and they’ve built in a lot of redundancy. With all the glitches, gmail, docs, etc are largely working just fine, allowing for the odd calendar reminder that comes three hours after the event. And five minutes later. And again.
But, largely, it works. Digital communism!
Oh, and if you want the hardcore stuff (you can’t really imagine running an IDE in a browser… (oh, unless it’s an IDE for the browser)), then get some specialised Windows or Linux machine and go play with the other geeks….
Filed under: Uncategorized | Leave a Comment
Tags: Browser, Chrome, Cloud, Computers, Future, Google, Google Chrome, Sun
This was first published in April 2006. Spring was a novelty. Even more so in a British life assurance company – that’s not your West Coast start-up. So please take it in context. I only re-post this, because it was the most linked to page on my old blog (with both positive and negative comments). I actually tried to recreate the same permalink for it but failed – WordPress won’t let you alter the date. I still think it illustrates DI and its spirit better that the Spring documentation. Also, do not take this as an endorsement of Spring. Spring is now mainstream and some bits of it are as vexatious as J2EE, nowadays I’d probably go for Lift on Scala. That does not invalidate the DI advantages though – testability, clarity, fail-fast mentality, clear contracts, etc. But the Scala version emphasizes my point here – if you have it in the language you don’t need a framework. Scala has it all in the language. Java had a lot of it in the language, but we failed to pay attention. Everything you can write in XML you can write in Java. And it’s type safe. As Dave Thomas put it, Java developers just don’t like writing Java. I sympathise. Oh, and nowadays, I’d go for constructor injection with eager assertions.
Here it comes, as it was, not one letter altered:
Dependency Injection Without Frameworks
Posted on 04/16/2006
I had to do this really small app recently. I wanted to use dependency injection, which I have come to really like now, but it seemed absolutely ridiculous to dump the spring jar and the few megs of dependencies in a project that only consisted of 20-odd classes.
So I decided to roll my own.
Initial thoughts
The main thing is – I want the classes to be unconcerned about their collaborators – they just declare a property of some interface type with getters and setters, and leave somebody else to assemble the whole thing. Thus, in the spirit of DI, you achieve very loose coupling between the objects, which simplifies the design and improves testability.
So, I need to design and write my classes as if for a framework – they would only depend on interfaces and not bother with the implementation. I decided to use setter injection. The only problem was: How do I assemble the whole thing? Looking at Spring again, I decided to have one servlet, which accepts all the requests and delegates their handling to request handlers. On initialisation,the servlet would build the whole application. True to the single responsibility principle, though the servlet would not do this itself – I decided to have an ApplicationAssembler interface and implementation, which would be responsible for the wiring of the components.
It was obvious, that the ApplicationAssembler would be the equivalent of Spring’s XML wiring declarations, except for simplicity, my implementation would just build them using Java. Note that this means there’s a compile-time dependency between ApplicationAssembler and just about everything, but I can live with this just fine, because it’s logically correct, and the individual classes are still very loosely coupled. If I wanted to remove the compile-time dependency, I could always make some XML or Groovy based application assembler.
Here’s a more specific scenario – The servlet has a map of requestHandlers, mapped against their urls. When it loads (init method), it makes an ApplicationAssembler and asks it to populate all the handlers with fully injected collaborators. From then on it’s easy – once a request arrives, the application looks up the fully populated handler and asks it to do the job. Some sort of abstract handler could provide the recipe for the common bits (validate, do business, redirect), and concrete handlers could implement the details if relevant.
At this point I got a bit worried – am I going to do more work than if I had just used Spring? Hm…. we’ll see. Also, it seemed a bit odd, that all I had in my whole application (at the top level) are request handlers. Is really everything in a simple web app a request handler? Or does this approach hide the rest… Hm… As I said, we’ll see.
Design
I sketched a small picture, and it did look quite neat – Mostly the fact that the dependencies were quite minimal. The ApplicationController (that’s how I named the servlet – I know – somewhat unimaginative) depended only on the ApplicationAssembler interface and the abstract RequestHandler. This really is the whole thing:

I have two request handlers in this example, RegisterUserRequestHandler and ShowUserHoldingsRequestHandlers. The two business objects are DataStore – to save the new registration and Mailer – to send the reg confirmation.
Here’s one request handler:
public class RegisterUserRequestHandler extends BaseRequestHandlerAdaptor {
// Collaborators
private Mailer mailer;
private DataStore dataStore;
public void setDataStore(DataStore dataStore) {
this.dataStore = dataStore;
}
public void setMailer(Mailer mailer) {
this.mailer = mailer;
}
public void handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
....
dataStore.insertUser(userData);
mailer.sendConfirmation(userId);
.....
}
}
I’ve removed the details, but the main concept is shown well – it declares the mailer and dataStore as interfaces, and setters for them, and that’s it. It’s down to the assembler to set the actual instances. Not only is this simple, but when writing testing this class, it’s easy to just set some mocks instead of the real implementations.
I will write the application assembler to wire it all together as shown on this diagrams for RegisterUserRequestHandler:

and ShowUserHoldingsRequestHandler:

The code that wires it all together is actually quite simple:
...
public class SimpleApplicationAssembler implements ApplicationAssembler {
public Map buildRequestHandlers() {
// Make the map for the request handlers
Map requestHandlers = new HashMap();
// Make a mailer
SimpleMailer simpleMailer = new SimpleMailer();
simpleMailer.setSmtpServerUrl("mail.supplesoftware.com");
// Get a datasource
DataSource dataSource = null;
try {
dataSource = (DataSource) (new InitialContext()).lookup("jdbc/MyDataSource");
} catch (NamingException e) {
throw new RuntimeException("Datasource jdbc/MyDataSource not found");
}
// Make a data store
SimpleDataStore simpleDataStore = new SimpleDataStore();
simpleDataStore.setDataSource(dataSource);
// Make the request handlers
RegisterUserRequestHandler registerUserRequestHandler = new RegisterUserRequestHandler();
registerUserRequestHandler.setDataStore(simpleDataStore);
registerUserRequestHandler.setErrorView("/regform.jsp");
registerUserRequestHandler.setSuccessView("/registered.jsp");
registerUserRequestHandler.setFormView("/regform.jsp");
registerUserRequestHandler.setMailer(simpleMailer);
requestHandlers.put("/register.shtml", registerUserRequestHandler);
ShowUserHoldingsRequestHandler showUserHoldingsRequestHandler = new ShowUserHoldingsRequestHandler();
showUserHoldingsRequestHandler.setErrorView("/error.jsp");
showUserHoldingsRequestHandler.setSuccessView("/showfunds.jsp");
showUserHoldingsRequestHandler.setDataStore(simpleDataStore);
requestHandlers.put("/showholdings.shtml", showUserHoldingsRequestHandler);
return requestHandlers;
}
}
And this is the controller that uses it all:
...
/**
* Dynamic request handler for the DIWF example
*/
public class ApplicationController extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
/**
* RequestHandlers mapped on url
*/
Map requestHandlers;
/**
* Uses the ApplicationAssembler defined in the applicationAssembler
* parameter to populate the requestHandler map
*/
@Override
public void init() throws ServletException {
String applicationAssemblerName = getInitParameter("applicationAssembler");
ApplicationAssembler applicationAssembler;
try {
applicationAssembler =
(ApplicationAssembler) Class.forName(applicationAssemblerName).newInstance();
} catch (InstantiationException e) {
throw new ServletException("Can not make an ApplicationAssembler", e);
} catch (IllegalAccessException e) {
throw new ServletException("Can not make an ApplicationAssembler", e);
} catch (ClassNotFoundException e) {
throw new ServletException("Can not make an ApplicationAssembler", e);
}
assert applicationAssembler != null;
requestHandlers = applicationAssembler.buildRequestHandlers();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
service(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
service(request, response);
}
/**
* Looks up the request handler by the request url and delegates to it
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestHandler requestHandler = requestHandlers.get(request.getServletPath());
if (requestHandler != null) {
requestHandler.handleRequest(request, response);
}
else {
System.out.println("Request path " + request.getServletPath() + " not mapped");
response.sendError(404);
}
}
}
I noticed that some of the functionality is common between request handlers, so put a base abstract class between the interface and the concrete classes to implement it, like this:

From here you can go as simple or complex as needed. Even in this simplest of all examples, there’s some repetition, which can be easily refactored using the Recipe pattern, eg. The error messages must go in a resource bundle. Some of the request handlers functionality can be abstracted. The validation can be handled by predefined validators. The views can be rendered into XML and transformed using XSL. The definition of the app structure can be XML-ised instead of hard-coded, and so on, until it starts looking like you’re building your own DI framework.
At which point it’s probably wise to switch to an existing one.
Afterthoughts
- I could have used a groovy script to do the wiring (ApplicationAssembler). That would mean I could change some implementations without recompiling. Don’t think that would happen in reality, though.
- There’s a clear distinction here between two main sorts of objects – the main players – request handlers and business logic objects, which are durable and stay there for the life of the app and the bits that you just pass around and dispose of, such as Price, or UserFeedbackForm. The main players are built by the ApplicationAssembler and there are limited number of instances of them. The disposable ones are made on the fly. It’s allright for an object to make one of them, because it is not in any form of compositional or aggregational relationship with it.
Advantages over using a framework
- It’s simple
- The wiring is strongly typed. Compare to XML.
- It’s easy to sell. In some companies, the mention of Spring or Pico will earn you nothing but pain. This allows you to do DI without irritating the elderly. Because the objects are still written the DI way, it’s easy to migrate to a framework later.
- This approach is much simpler than using a framework, but at the same time the whole mechanism is exposed for all to see and understand. The less experienced developers do not face some incomprehensible thing that works as if by magic, and actually have some chance of understanding the actual meaning of DI and IOC.
Disadvantages
- When the app starts getting big, the ApplicationAssembler will get messy. Although in the tiny example I provide here, it’s still quite neat. I suppose it could be split into parts, but a framework has all these considerations sorted already.
- The frameworks offer various strategies for instantiating objects (beans). Here it’s done once, so all your objects will be, for all intents and purposes, Sin*&%#ons. Or Moretons. But you can’t get it to create a new one every time, or maintain a pool, at least not easily. You’d have to give factories to your objects, instead of other objects, which in some ways defies the point.
- The previous point raises questions about concurrency – I’m not going to think about this now, because it’s out of scope, but clearly, state should be avoided and as the app grows you’ll have to think about pooling and stuff.
- Some frameworks, notably Spring actually give you a lot more than just dependency injection, including, transaction management, aop, etc. goodies, you’ll have to go a long way to write these yourself.
Filed under: Uncategorized | Leave a Comment
Wayback Machine
I was delighted to find my old blog neatly folded and archived on the marvelous Wayback Machine. I spent hours trying to convert it to WordPress and eventually gave up and just dumped it, blogging some lofty nonsense about detachment. It turns out the Wayback Machine’s got it all – you can just get it there. So, what I am going to do over the next few weeks is re-post some of the posts I had there that seemed to be reasonably popular. Especially that controversial Roll-Your-Own-Dependency-Injection one….
Filed under: Uncategorized | Leave a Comment
Swapping classes
I’ve been thinking about the way Log4J, commons logging, SLF4J, Logback and the related libs blatantly swap classes with the same qualified names. Like, you take this jar out, put the other jar in and you’ve got a different implementation. One example is the StaticLoggerBinder.
The interface is defined in the API and there’s a default implementation there too, but if you want to change it, you make a class with the same qualified name and then swap another jar into your dependencies. A few years ago I would have said that’s way dodgy and shouldn’t be done. But now that I’ve used it for some time, I don’t really see what the big deal is. It’s the ultimate case of convention over configuration.
I have had the odd problem where transitive dependencies filter in and spoil the party, but largely, it’s as pain-free way to change the logging implementation as any. You just change your dependencies! It does get confusing occasionally, but once you get your head round your dependencies (which you should anyway), it seems a lot simpler than having even more configuration items. See this for an intuitive clarification of how it works with Log4J, SLF4J and a bizarre faking of Log4J that re-routes it to SLF4J.
Filed under: Uncategorized | Leave a Comment
Quick sort in Scala
def qsort(list:List[Int]):List[Int] =
{
list match {
case x::xs => qsort(xs filter(_<x) ) ::: x :: qsort(xs filter(_>x))
case Nil => Nil
}
}
print(qsort(List(4,6,5,0,2,3,1,7,8,9)))
Short and sweet!…
Filed under: Uncategorized | Leave a Comment
Hacked!
OK, I was unfair on Google. The site had been hacked. I (or my ISP) should have been more careful. Yet, I don’t see what I could have done better, short of hiring a bunch of hackers to verify my ISP’s security procedures. Cause, really, there’s nothing in that web site as such that would allow it to be hacked through code injection or something. Or at least I don’t think there is, but I’m not a hacker. I am very apprehensive now, and totally daunted by the massive consequences. I can apply for a review of the site, but I can’t imagine a bunch of people on the other site dealing with these very efficiently. And how would they be in a position to verify a site’s security, unless they are better hackers than the best out there. So, once you’re hit, you are, through no fault of your own, destroyed. You may question that bit about the no fault, but as much as I can educate myself on hacking techniques, I’ll never be as good as the kids out there, I have a day job to do too. Beyond maintaining good passwords and choosing your ISP carefully, I don’t really see what Joe-the-webmaster can do to stop it. So, anyway, once you’re hit, you’re practically destroyed. That site will probably never show up at the top, the way it used to. Even if they wanted to not be evil and investigate and judge what’s right or wrong, there’s no way they’ll have the capacity, there’s probably millions like me out there. Not to mention the moral responsibility of being the judge of something that will ultimately result in actual wealth redistribution. Grumble, grumble, grumble. Simple life in the woods seems like a tempting proposition.
Filed under: Uncategorized | Leave a Comment
I’ve been asking this question for some time now. When will Google become the next corporate monstrosity that we all love to hate? Two events from the past 24 hours tell me that time is coming.
First event. I got an email from “adwords-support”, saying that “Your account XXX-XXX-XXXX has been suspended because we’ve determined that there’s a high probability your site may be hosting or distributing malicious software.” The site sells window blinds! Honestly?! Malicious software? All you can get from that site is plain, standards compliant HTML and CSS! What a bunch of plonkers! Oh, sorry, it’s not humans that do that, is it? Or should this be, what a bunch of plonkers wrote that rubbish? Then I go to the site, and I see that it’s been blacklisted. It’s a reported “attack site”. Wait to be attacked by the avalanche of designs of blinds and awnings we have, it will blow your mind and make you fall in love with a penguin.
Anyway, that’s not the problem. Everyone gets it wrong. But this is a paid service. I have come to expect from the real world, that when I pay for service, any glitches in it would not affect my friend’s company in this MASSIVELY detrimental way. MASSIVELY detrimental. No warning! Nothing! Bang – game over! You have been shot.
The other problem is, what do I do now?? There’s a link in the e-mail, saying, if you believe this is wrong, contact us. I won’t be contacting a human though, will I? They don’t do “Customer service” there. That’s for the old fashioned, stupid companies that like to take an evening off once in a while. Plus, the damage has been done. I hope it ends up in the papers (Bulgaria is a small country).
Second event. I was busy at work, so I had forgotten about that. At lunch, I thought I’d have a look at my email on my internet enabled phone. Gmail, to be precise. I use the phone’s browser to read it, because I’m not that hot on the email client. So, only several hours after the adwords rubbish, I get a “We’re sorry, but Google Mail is temporarily unavailable. We’re currently working to fix the problem. Please try logging into your account in a few minutes.” Well, you know what, Google, I have come to rely on your Gmail thingy. Not just for email. For remembering things. It’s my external RAM. Because your search is so good. But is it, now?… It certainly was. But so was its reliability. I hear it blew up recently too, though I didn’t get caught in that. Now, I’m thinking, hang on…. I will be a very, very, very sad boy if my email data goes down the drain. Like, properly sad. Like The Little Prince for his rose, that caliber of sadness….. VERY sad! Can I trust this thingy out there somewhere in the cloud???
Filed under: Uncategorized | Leave a Comment
Recent Entries
- Upgrading to Clojure 1.3
- Captured requirement
- Conditional Tail Expectation calculation in Scala
- Why is Google pushing Chrome?
- Dependency Injection Without Frameworks
- Wayback Machine
- Swapping classes
- Quick sort in Scala
- Hacked!
- When will Google become the new Microsoft
- Conversion between JCL, SLF4J, log4j and logback
Categories
- programming (5)
- Uncategorized (13)
