Clojure utility functions – part I

Cross-posted from Zolo Labs.

 

I kept using an extra line of code for this, so I decided to create the following function:

Another extra line of code can similarly be removed using this function:

Obviously, the raw forms (i.e. using doseq or map) can be far more powerful when used with more arguments. Still, these simple versions cover 99.9% of my use-cases.

I keep both these (and a few more) in a handy utils.clojure namespace I created for just such functions.

The technical priorities of a startup

There should be none. I mean, sure, there should be some, but just enough to get over the hump of creating testable hypotheses. The hypotheses, should in turn, be iterations on your product – and they should be in the hands of your users.

There are just so many other things that cause a startup to fail, that optimizing the technology stack is just the wrong place to spend any resources. This doesn’t mean you shouldn’t use promising technologies if they can solve clearly anticipated problems. It does mean that you don’t want to waste resources in premature scaling. This, of course, applies to all aspects of your startup – tech, sales, support, etc. 

As far as tech is concerned, pick the best tools for the job, and then move forward quickly. Don’t worry about being perfect (in fact, don’t be). Get traction first – no one cares how amazing your backend is.

The tech stack of the startup

This post is about startups and technology. Of course, nothing will help you if you don’t have a market, or traction, or a business model, or an actual product, or good people. Those are conversations for another day, but now, here’s what I’d use if I’m starting a startup today:

Programming languages:

Data stores:

Data processing:

Machine learning:

Messaging:

Version control:

Builds:

Cloud:

Functional testing:

Project management:

Am I missing stuff?

Software development agility – bottom-up design and domain-specific languages (DSLs)

It’s been nearly three months that I’ve been working at Runa. And in that time I’ve worked with the team to get a lean and agile process in place, and while we’re not there yet, things are getting more and more focused every day.

I’ve also been working to significantly re-factor the code that existed, as we get ready to get the first beta release out the door. In this post, I’d like to talk about one aspect of our design philosophy which I’m glad to say has been working out really well – bottom-up design (and an associated DSL).

Before we decided to change the system, it had been designed in the usual top-down manner. Runa operates in the online retail space – we provide web-based services to online merchants, and while we have a grand vision for where we want our platform to go, our first offering is a promotions service. It allows merchants to run campaigns based on a variety of criteria. Merchants are a fussy lot, and they like to control every aspect of campaigns – they want to be able to tweak all kinds of things about it.

In true agile fashion, our initial release allows them to select only a few parameters. Our system, however, needs to be extensible, so that as we learn more about what our merchants need, we can implement these things and give it to them. Quickly. And all of this needs to be done in a changing environment with lots of back-and-forth between the business team and the dev team.

So here’s what we came up with – it is an example of what we call a campaign template –

campaign_template :recapture_campaign do
  title is 'Recapture'
  subtitle is 'Reduce cart abandonment rate'
  description is 'This campaign presents offers to shoppers as they abandon their shopping cart.'

  #adding criteria here
  accept required time_period_criteria with defaults start_date('1/1/08'), end_date('12/31/10')
  accept required product_criteria with no defaults

  hardcode visit_count_criteria with number('1')

  #more criteria
  reject optional url_referrer_criteria with no defaults

  inside context :view_badge do
    never applicable
  end

  inside context :abandon_cart do
    allow only customer_type_criteria with customer_type('visitor')
  end

  inside context :cart do
    allow only user_action_criteria with user_action('accepted_recapture')
  end

end

A campaign template behaves like a blue-print of an actual campaign. Sort of like the relationship between a class and an object. In a sense, this is a higher-order description of just such a relationship. The (computer) language now lets us speak in the domain of the business.

There are a couple of reasons why our core business logic is written like this –

a) It lets us communicate easily with the business. Whenever a question about a rule comes up, I bring up the associated template up on the screen, and make them read the ‘code’. Once they agree thats what they mean, it just works, because it is real code.

b) Since this is in essence a way to script the domain model, it has forced a certain design upon it. All the objects evolved in a bottom-up manner, and each does a very specific thing. It lends to a very highly de-coupled design where objects collaborate together to achieve the higher goal, but each is very independent of the other.

c) This notation makes several things easier. One, the actual business rules are described here, and they just work. The other thing is that we’re able to use this same representation for other things – for example, our merchant GUI is completely auto-generated off these template files. Menu items, navigation, saving, editing, error-reporting, everything is generated.

This allows very fast turn around time for implementing new concepts, or making changes to existing ones.

It’s an internal DSL written in Ruby, and does whatever it can without any extra parsing, as you can probably imagine. I will write about the specifics of how this is implemented in future posts. For the moment, I would like to stress, however, the importance of the bottom-up approach. Because our domain model is made up of many small objects (instead of a few larger ones), each representing a tiny aspect of the domain, we’re able to put them together and fashion more complex beasts out of them. And the combinations are limitless, bounded only by business rules. This is where the power of this approach lies.

The DSL itself is almost only a convenience!

The age of the mobile web is here

This is it. If there was any doubt the future of handheld devices was the mobile web, it should be laid to rest now. As a strategy for allowing 3rd party developers to write applications for the iPhone, Apple has embraced the mobile web. And they plan to support all the ‘Web 2.0’ standards – which is just another way of saying that the mobile browser’s DOM will be predictable, and that Javascript will work as expected. Why won’t it, after all, the ‘mobile’ browser is a full-fledged desktop version!

If any of you have ever tried to develop mobile web-apps that used AJAX (esp. through the use of the popular AJAX libraries for the purpose – Prototype/Scriptaculous or Dojo), you know what I’m talking about. None of the mobile browsers really work well at all. They are all broken in some way or the other – and to add to the fun, they’re broken in different ways.

So – how is Apple going to fix the issue? By side-stepping the mobile browser entirely. Just take a desktop browser and make it available on the mobile. Perfect! And this is Apple’s official strategy for externally developed applications! So the critical mass is ready to happen…

And this will also see the beginning of the end of the walled-gardens of the carriers. If they don’t own the access to mobile applications, then they can’t control it. The reason they do control it, is that for the most part, no one wants to download and install things on their phone. Either they’re not technical enough, or things break after you install the wrong or badly developed application. So most people just use whatever is ‘on-deck’. And those applications are completely controlled by the carriers. No more! If the mobile web becomes popular, that’s the end of that!

Yet another way the iPhone will change the world.