Monday, December 8, 2014

Buttons missing from Commerce Manager in Internet Explorer

I recently encountered an issue with all buttons missing from the Commerce Manager when running it locally in Internet Explorer:


Deploying the Manager to any other environment such as test or production, the buttons appeared as they should. I also had this issue for several different Commerce Managers, so it was quite clear that the problem had something to do with my machine, specifically Internet Explorer as it worked fine in all other browsers.

Problem:

Internet Explorer had been set to display all intranet sites in Compatibility View, and apparently the Commerce Manager was viewed by IE as an intranet.

Solution:

Tools -> Compatibility View Settings -> Uncheck "Display intranet sites in Compatibility View" and all your buttons will appear.


Tuesday, November 25, 2014

A summary of TechDays Stockholm



Last week, I had the honor of attending TechDays Stockholm as a speaker. It was the first time I've been to this conference and the size of the it surprised me. With approximately 1400 participants and 9 parallel sessions, I got the same vibe from TechDays as I've done from NDC Oslo and JavaZone. The most obvious difference being that TechDays is organized by Microsoft and therefore mostly concerns development on the Microsoft platform.
Mary-Jo Foley at the keynote

Before the conference, what I looked forward to the most was the keynote with Mary-Jo Foley, Albert Chum, Sara Kullgren and Jonas Persson. Unfortunately, the keynote was not as technical as I had hoped, at times it felt more like a sales pitch, which of course is unnecessary as the audience had already "bought" what they were trying to sell. That being said, it was great to see a changed Microsoft, a more open company that wants feedback from the community and are not afraid to admit the wrong turns they have made in the past. Because they have made mistakes and they've had to restore some faith among the participants of the community, but from the energy I could feel from the attendees at TechDays, I think the faith is close to restored.

"Women in technology" lunch
 The first day of the conference, there was a "Women in technology" lunch. I had received a newsletter about this a week or so before the conference and of course I had to sign up, very curious of how this lunch would play out. While I'm ALL IN for women in tech, I tend to find some of the women networks out there a bit extreme, I feel as some of them are creating a greater gap between women and men by inflicting a "is us against them" mentality. Putting a bunch of women together in a room is not how you get more women into tech, so I was very happy when I saw that men were also invited to this lunch. The lunch was a success, great food, champagne and many inspiring women and men discussing the topic of women in technology. The speaker who made the greatest impression on me was Jonas Persson, the CEO at Microsoft Sweden. His views and his focus on including women in the organization are simply amazing.

TypeScript for C# developers by Chris Klug
As a speaker at a conference, I find it rather difficult to focus on the content of other sessions before I've finished my own. However, I try to attend as many sessions as possible and some of them always turn out to be good enough for my mind to relax a little. I had the pleasure of attending "TypeScript for C# developers" by Chris Klug, a funny guy with a great topic who definitely got my mind of my own session before I was up for the task myself. My session went well, I got some great feedback and although I had some technical issues (not being used to using Powerpoint), I'm very happy with the result. Thank you to everyone who attended!

During the conference, an interview I had with Microsoft Norway a couple of months ago was published on their blog. How is that for timing! They're interviewing lots of developers as inspiration for others, a great initiative and I'm looking forward to upcoming posts. I know there are some awesome developers coming up! You can read my interview here..

Nerdy party games by HP
At the party, I found some of the women I had met during the "Women in tech" lunch before I bumped into Mark McEvoy (where there are Irish, I tend to find them) and Chris Klug (from the TypeScript talk I had attended). All in all a fun night with some nerdy games, a very loud band and new aquaintances. 
TechDays Stockholm, I had a blast! Congrats on a great conference and thank you for having me! 

Monday, November 10, 2014

A retrospective of last weeks presentation at NRK

A couple of months ago, I gave my "How to create a Web API no one wants to use" presentation at CodePub Oslo, a meetup for female developers. At this meetup I met Anastasia, a women working at NRK, "the Norwegian government-owned radio and television public broadcasting company, and the largest media organisation in Norway". I had a great conversation and discussion with Anastasia after the presentation. It was very refreshing as it's not often I get to discuss technical topics with other women.
A couple of weeks later, Anastasias team leader, Marianne, contacted me wondering if I was interested in giving the same presentation at NRK. And of course, I said yes. As I'm doing the same presentation at TechDays Stockholm at the end of November and NDC London in December, I thought this was a great opportunity to get some extra practice. 
At the moment, NRK is doing some very interesting API development, which I'm hoping one day will result in a public API (pretty, please?). Being of one those weird people without a television, I'm a huge fan of their streaming services, http://tv.nrk.no/ and http://tv.nrksuper.no/ and I'm still baffled that they're supplying all this awesome content to their users for free. I would gladly pay for these services, so I'm hoping we'll see a change in the license-model soon! 
Having these great services, it's not a big surprise that there's some pretty cool technology behind it all. A lot of the applications NRK have developed, and continue to develop, are hosted in Azure, and they have a high focus on continous integration and testing. These are things we all would like to see in our projects! For more information on the technology choices they've taken, I recommend reading "Derfor kjører NRK i nettskyen"
Thank you, Anastasia and Marianne for inviting me! I hope to see you again soon! 

Wednesday, October 29, 2014

Generate an order number for your cart in EPiServer Commerce

Many payment services, such as PayEx, require that you pass in an order number when processing payments. This makes it very easy to track payments as you instantly know which order the payment belongs to. At the same time, if you don't want to generate an order before the payment has been processed, where does this order number come from? In this blog post, I'll show you how to can generate an order number for your Cart and then later generate a purchase order with the same order number.

The Cart in EPiServer Commerce has a CreateOrderNumber delegate you can use to define how the order number for your PurchaseOrder will be generated. EPiServer has a great overview of how this works in their Changing order number sequence article. As the article states, the method you define for the CreateOrderNumber delegate is run in the SaveAsPurchaseOrder method, but we don't want to run this method until after the payment is already processed. So what do we do?

We'll still use the CreateOrderNumber delegate, but we've added a lambda expression:

public void BeforeProcessingPayment(Cart cart)
{
   var orderNumber = GenerateOrderNumber(cart.OrderGroupId);
   cart.OrderNumberMethod = c => orderNumber;

   // Save cart and process payment, passing in the required orderNumber
}

// This is the default order number generator in EPiServer Commerce, 
// you can change this around if you want a different format
private string GenerateOrderNumber(int orderGroupId)
{
   string str = new Random().Next(1000, 9999).ToString();
   return string.Format("PO{0}{1}", orderGroupId, str);
}

In the BeforeProcessingPayment method, we're generating an order number and using a lambda expression to set the OrderNumberMethod delegate to this value. This means that you can process the payment and call cart.SaveAsPurchaseOrder() after the payment has successfully been processed. The PurchaseOrder will then receive the same order number as you generated for your Cart.

Now, that wasn't too hard, was it?

Thursday, October 23, 2014

"Oh, a woman, she must be the project manager"

Coffee in one hand, laptop in the other, you're entering a conference room to spend the next hour or so with a handful of people you've never met before. You greet the lot by a quick handshake, first the women and then the two men, before you sit down.

You're there to supply the details as to how the other attendees can integrate their systems against yours, and the woman starts firing away questions. Half an hour of discussions passes and the questions get more and more technical, the woman is still the one who initiates most of them while the two men contribute with their opinions.

The big question is: "When you are to ask a question in return, a question which a developer must answer, who do you direct it to?"

This scenario played out in one of my meetings yesterday and the guy made it quite clear.

"I'm going to address you as you look like the developer", he said and turned to my male colleague.

"We're all developers", my champ colleague replied as I could feel the blood pumping from frustration. I decided to let the comment slip, and I continued to ask questions for another hour.

Gender equality has come quite far in Norway compared to most other countries in the world, even in the tech industry. So encounters such as yesterday's meeting are rare, but they do happen occasionally. When they do, how do you react?

I chose not to say anything and continue the meeting in peace. I didn't feel as though he was intentionally rude, he was simply ignorant. Ignorant of the fact that there are female developers out there, so clearly I must have been the project manager. Had he been mean, I would have said something. But the problem with speaking up about these issues is that you quickly replace your "she's a women, she can't be a developer" label with the "she's an emotional, hysterical feminist" label. And I believe that label does more harm than good.

So my strategy is to prove them all wrong. Like I did earlier this year when I ran into my "you only got this job because you're a woman" ex-colleague before my session at NDC Oslo. One by one, I'm going to prove to them that I'm capable of being an awesome developer AND a woman. Because, believe it or not: There's no testosterone requirement to our profession.

Friday, October 17, 2014

My first six months as a female tech speaker

I'm not the only one who thinks getting up on stage is scary, if not terrifying. Most of us recognize the feeling of not being brave enough or good enough. "Why would someone want to watch my presentation when there are so many out there who know more about this than I?" This is what a lot of developers feel and so did I over a year ago. But that has changed, and I'd like to tell you the story of how it all turned around.

There's a difference between being good at writing code and being able to talk about code, or technical concepts for that matter. I probably owe half my career to a couple of recent and present colleagues who have taught me a lot by talking about code. Talking about code inspires me, but at the beginning of my career I was uncomfortable doing it. What if I used the wrong word? What if I said something wrong? I decided to turn the question around: what would my colleagues do if I said something wrong? Well, some wouldn't say anything at all, other would correct me and one would ask me the right questions so I would realize and correct the mistake myself. No one would laugh, talk behind my back, or label me as useless.

I put on a brave smile and some fake confidence, and I started discussing code with my colleagues. It didn't take long before the fake confidence became real, and it grew fast. Discussing and talking about code had a side effect I hadn't thought about, suddenly my learning curve sky rocketed. Being able to understand new technical concepts explained to you without seeing them written down gives you possibilities you didn't know existed.

After a while, I felt comfortable and confident  talking about code with my colleagues, and I had become somewhat addicted to the learning experience that comes with it. I wanted more, but how?

I used to love public speaking when I was younger. Being part of the European Youth Parliament, I got a high from standing on a stage in front of hundreds of my peers. But somehow, over the years, that love had disappeared. The thought of doing that sort of thing again terrified me, but there was a small part of me hoping I could rekindle the fascination I once had.

I gave it a shot, I signed up for a course on public speaking on Coursera and I spent months creating presentations, recording them and having people all over the world give me feedback on the content and my performance. Of course, speaking to a web camera, recording yourself is not as scary as standing on a stage, you mostly just feel silly. So at the end of the course, I gave myself an exam: To submit a lightning talk abstract to Booster Conference 2014 in Bergen.

Weeks passed and I received the message that I'd been accepted as a speaker. I flew to Bergen and back, completely exhausted after a great conference. The talk was fine, given that it was my first. In hindsight, I've realized how hard it is to say something useful in 10 minutes. As for the performance, it seems like I completely forgot how to smile and  relax.

A couple of months later, I found myself standing on stage at NDC Oslo, nauseous, wondering why the hell I would torture myself like this. My presentation was at the same time as Hanselman and Crockford, so I was amazed that someone turned up for mine. But people showed up one by one, and I survived my first full hour on stage. Still, my performance was stiff and rehearsed, and the content not much better than satisfactory.

That was all about to change though. I'd been asked to speak for the .NET user group in Oslo and I had decided it was time for a completely new presentation. The one I'd held so far simply didn't do the trick. I had worked on the presentation for a couple of weeks when my grandpa had a heart attack and was put into a coma. I can't remember much of the following weeks, but the day of the .NET user group meetup I'd spent the day in the hospital saying goodbye to him. I wanted nothing more than to go home and sleep, my mind and body completely shattered from trying to understand how someone could just disappear without any warning. But I had spent so much time preparing this presentation, and I didn't want all that to be a waste of time. So I went through with it.

Going through a crisis, you quickly find yourself with new perspectives. That happened to me on my way to the .NET user group: I realized that in the larger picture, this presentation didn't matter. Who would care if I said something wrong? If the presentation turned out terrible, if I made a complete arse of myself, I could simply quit. I could walk away from this speaker project I've thrown myself into at any time, no one is forcing me to go on.

Thinking all these things took away my fear and I was no longer nervous. As a matter of fact, speaking to a room full of developers was a nice break from the rest of the terrible events I'd gone through that day. Did I say something wrong? Yes, I did. And the audience corrected me when I did, which I really appreciated. But still, being a pretty inexperienced speaker, I rocked the presentation! It didn't seem rehearsed, I engaged with the audience and we had some nice discussions going. I think I might have cracked the code, figured out the secret.

The secret is to realize that it doesn't matter if you blow it, being a speaker is (for most people) not the most important thing in your life. For me, it's actually quite far down on the list, I do it for fun.

Since the .NET user group meetup, I've done the same presentation at Code Pub Oslo. Later this month I'll be speaking for the developers at NRK. In November, I'm on for TechDays Sweden and in December it's NDC London. So many amazing opportunities I'm extremely grateful for being given!

Then what? Who knows, but it doesn't really matter, does it? If I still enjoy this at the end of the year, I'll go on. So what's my tips to all of you out there who want to become a speaker? There are plenty:

1) Creating a presentation takes a lot of time, more time than you think! For my last presentation, I've probably spent about 40-50 hours doing research, putting it all together and rehearsing. When you're done though, you can use your presentation several times.

2) Don't rehearse too much. This is what I did for my first presentations and the result is that you're not able to show your true self up on that stage.

3) Find a thought that makes you relax and that takes away your nerves. For me that thought was: "All this doesn't really matter"

4) Talk to experienced speakers and don't be afraid to ask questions. I've received some great advice from Johannes Brodwall, Niall Merrigan, Hadi Hariri and Troy Hunt when I've asked for it.

5) Don't be disappointed if you submitted a paper for a conference and don't get accepted. This happens to everyone, it has happened to me twice already. You should be glad all conferences are different, imagine how boring conferences would become it they all had the same speakers?

6) If you want to get started as a speaker, then throw yourself into it. Start by presenting something for your colleagues, contact a local meetup, or submit a lightning talk to see if this is something you'd enjoy doing.

Thursday, October 16, 2014

Apple and Facebook freezing their employees eggs

I'm one of those women in IT who wants to have it all: A family and a career. Had I worked at Facebook or Apple, they would tell me that wouldn't be a problem at all. Because they give their employees "baby-cash", extended family leave and now: They can freeze your eggs.

They've decided to interfere with the most private part of a womens life, reproduction. As if freezing a womens eggs will postpone her wish for a family. As if every woman is willing to put their private life on hold for, let's say, 10 years, so that the employer can have their cut of her time. And what happens after 10 years? When the woman with the frozen eggs realizes that her employer is even more dependent on her now than they were before? Is she going to wait just a little bit longer? I mean, her eggs are already frozen, why not wait a couple of years longer? Until her body is not able to carry forth a child. Until her husband is tired of waiting. Until she's come so far in her career she decides to just forget all about those eggs.

Some women might find this to be a great solution, and that's great for them. But other women will feel pressured. Imagine a woman hoping for a promotion, and the only other candidate has made it very clear that she is willing to freeze her eggs to get the job. Will she feel pressured to do the same? My guess is, probably. If she wants children, freezing those eggs wont magically stop her wanting, there's a mental part to the equation that these companies are not thinking about.

Freezing eggs is not a solution for balancing a family and a career. It's as if we were to solve a famine crisis by supplying a pill that switched of hunger. The famine victimes would still need food, the pill would only postpone the problem and in my opinion make it worse. 

I hope Apple and Facebook will think twice about this. I hope they will address the true issue here, how to make the industry accept a women balancing her career with a family. Without discrimination, without making her feel the extra pressure. 

I have a job that I love and a beautiful family. I'm balancing for all that it's worth, and it's exhausting but it's worth it. My employer makes it possible and not once have I felt pressured or discriminated against. Surely, if they can do it, you would think Apple and Facebook could do the same?

Monday, October 13, 2014

Dev.Cast interview

Some weeks ago, I had a nice chat with Dag Köning from Microsoft Sweden about my presentation "How to create a Web API  no one wants to use". The podcast was released today, and you can listen to it here (in Swedish and Norwegian). Make sure you check out his other Dev.Casts as well, there's some great stuff there!



I'll be speaking about this topic at TechDays in November and at NDC London in December, so if you're attending any of the conferences, come say hi!

Wednesday, October 8, 2014

How to hide SeoInformation in EPiServer Commerce

When working with EPiServer Commerce you will see that all products, variants and categories automatically will receive a block in the Information tab called "SeoInformation". In several of our projects we don't want to display this block, we'd rather create our own SEO properties.

The SeoInformation block comes from the ISearchEngineInformation interface that all the following classes implement: NodeContent, BundleContent, PackageContent, ProductContent and VarianContent. So if you don't want the SeoInformation property to be displayed on any of your products, variants and categories, you will need to override the property on all your classes inheriting from ProductContent, VariationContent and NodeContent. 
For example: 
public abstract class BaseProductData : ProductContent
{
    [ScaffoldColumn(false)]
    public override SeoInformation SeoInformation { get; set; }
}

Now, you might be tempted to add an Ignore attribute to the property as well, but if you do that EPiServer will give the the following error when trying to publish: "Property with name 'SeoInformation' is not part of the ContentType definition"


Which of course, is logical as EPiServer won't find the SeoInformation property on the ContentType model. So if you find yourself receiving this error message, make sure you're not using the Ignore attribute on the property in question.


Thursday, October 2, 2014

Why do girls need science to be sparkly in order to find it interesting?

Is science different for men than women? Do women perceive scientifical concepts differently, or is our understanding of science any less?
No. Period.
NO!
The laws of science apply whatever your gender, religion, age or race. So why is it we keep seeing things like this?

"Science with a sparkle". Why do they think girls need science to be sparkly in order to find it interesting? And why shouldn't the boys be allowed sparkly science?

When I was a kid, I used to love chemistry sets (like this one) and electronics sets (like this one). I didn't need sparkles. Sparkles has no role in explaining how our world works, how research can give you the most amazing answers and how technology is making things we've previously only imagined possible.

Our first step of attracting young girls to the fields of science is by giving them the same education as the boys. Let them play and explore science together and that's when we'll start seeing sparkles!

Friday, September 26, 2014

How to create a Web API no one wants to use: Exercises

Introduction to this blog series


Later this year, Netflix will be closing their public APIs. Twitter and Google have already restricted their APIs. Despite prominent tech-companies making drastic changes to their APIs, the number of APIs keeps growing steadily. Suddenly, everyone has a Web API. Your car has one, Chuck Norris has one, and worst of all, tech-companies with no focus on quality whatsoever has one. And who are using these APIs? Most likely, no one.
This blog series will take you through the pitfalls of creating a Web API. From a developers perspective, what mistakes will result in no one wanting to use your API?

Part 1: URI Design
Part 2: HTTP Verbs
Part 3: HTTP Status Codes
Part 4: Result formatting
Part 5: Versioning
Exercises

Exercises


Earlier this week I presented my "How to create a Web API no one wants to use" talk at Code Pub Oslo. Code Pub Oslo is a meetup for female developers, a very inspiring event! The organizers asked me to create a set of exercises to go with the presentation, and here's the result.

Exercise 1: URI Design


Imagine you have an API with the following endpoints:

EndpointDescription
…/books/Returns all books
…/books/id/5Returns the book with ID=5
…/author/Returns all authors
…/author/3/booksReturns all books written by the author with ID=3

a) Can you spot any inconsistencies in this API? How would you fix them?
b) Can you redesign the API so that the URIs are hackable?
c) Can you think of an alternative way of filtering the books on author?

Exercise 2: HTTP Verbs


a) Which of these methods are safe?
i. Registering a new user
ii. Retrieving the weather forecast for tomorrow
iii. Cancelling an order
iv. Removing a picture

b) Which of these methods are idempotent?
i. Registering a new user
ii. Retrieving the weather forecast for tomorrow
iii. Cancelling an order
iv. Removing a picture

c) Which verb should you use for the following methods?
i. Registering a new user
ii. Retrieving the weather forecast for tomorrow
iii. Cancelling an order
iv. Removing a picture

Exercise 3: HTTP Status Codes


Which status code should you return in each case?
a) The client asks for a record that does not exist
b) The client posts invalid data
c) There was a technical error in the API
d) The client creates a new record
e) The client calls an asynchronous method

Exercise 4: Result Formatting


You are developing an API for a customer who wants to support both JSON and XML results. Which type of result formatting should you go for?

Exercise 5: Versioning


a) You are developing an API for a customer who wants the version to be an optional part of the URI. Which versioning method should you use?

b) What if the customer wanted the client to specify both the version and the result format as part of a header?

c) Can you give an example of how such a header would look?


Wednesday, September 24, 2014

Find purchase orders by an OrderForm meta field in EPiServer Commerce

If you've added a meta field to an OrderForm, you can use the OrderContext.Current.FindPurchaseOrders method to find all purchase orders with a given value in that meta field. However, figuring out what the SqlWhereClause should be might not be completely straight forward, so I thought I'd share a solution.

I've added a meta field to the OrderForm called OrderStatus. This meta field will then show up as a new column in the OrderFormEx table in the Commerce database:



What if I want to find all purchase orders where OrderStatus is NULL? The following code would do the trick:

var searchOptions = new OrderSearchOptions
{
   CacheResults = false,
   Classes = new StringCollection { "PurchaseOrder" },
   Namespace = "Mediachase.Commerce.Orders"
};

OrderSearchParameters parameters = new OrderSearchParameters()
{
   SqlWhereClause = "OrderGroupId IN (SELECT OrderGroupId FROM OrderForm WHERE OrderFormId IN (SELECT ObjectId FROM OrderFormEx WHERE OrderStatus IS NULL))"
};

PurchaseOrder[] purchaseOrderCollection = OrderContext.Current.FindPurchaseOrders(parameters, searchOptions);

If you want to know more about how this works, you should check out EPiServer Commerce Order Search Made Easy (not sure I agree on the "made easy" part, but that's a different story).

Hopefully this will save you some time! 

Thursday, September 18, 2014

Using StructureMap with named instances in EPiServer

If you have several classes inheriting from the same interface, and you want your business logic to choose the correct class based on a criteria, you should check out named instances in StructureMap.

For example, let's say you have the following classes:

public class Facebook : IAuthenticationStrategy
public class Google : IAuthenticationStrategy
public class Forms : IAuthenticationStrategy

We have three implementations of IAuthenticationStrategy and the role of these classes is to validate the authentication credentials for Facebook, Google and Forms authentication.

Now, let's define the criteria as an enum:
public enum AuthenticationType
{
    Facebook,
    Forms,
    Google
}

If the user selects Facbook during login, the business logic validating the authentication will receive AuthenticationType.Facebook. If Google is selected, AuthenticationType.Google is used, and so on.

How can we use named instances in StructureMap to wire all this up? Let's define all our instances of IAuthenticationStrategy in our container:

container.Configure(
    x =>
    {
       x.For<IAuthenticationStrategy>().AddInstances(i =>
       {
          i.Type<Facebook>().Named(AuthenticationType.Facebook.ToString());
          i.Type<Google>().Named(AuthenticationType.Google.ToString());
          i.Type<Forms>().Named(AuthenticationType.Forms.ToString());
       });
});

Now all we have to do is create a Factory class passing in the AuthenticationType the user has selected:

public class AuthenticationFactory : IAuthenticationFactory
{
    public IAuthenticationStrategy Create(AuthenticationType type)
    {
         return ServiceLocator.Current.GetInstance(typeof(IAuthenticationStrategy), type.ToString()) as IAuthenticationStrategy;
    }
}

Last, but not least: Here's an example of how you could use the AuthenticationFactory to receive the correct instance:

public UserAuthentication ServerValidate(UserAuthentication userAuthentication)
{
    IAuthenticationStrategy authentication = _authenticationFactory.Create(userAuthentication.Type);
    return authentication.ServerValidate(userAuthentication);
}

Simple, right?

Tuesday, September 2, 2014

How to create a Web API no one wants to use. Part 5: Versioning

Introduction to this blog series


Later this year, Netflix will be closing their public APIs. Twitter and Google have already restricted their APIs. Despite prominent tech-companies making drastic changes to their APIs, the number of APIs keeps growing steadily. Suddenly, everyone has a Web API. Your car has one, Chuck Norris has one, and worst of all, tech-companies with no focus on quality whatsoever has one. And who are using these APIs? Most likely, no one.
This blog series will take you through the pitfalls of creating a Web API. From a developers perspective, what mistakes will result in no one wanting to use your API?

Part 1: URI Design
Part 2: HTTP Verbs
Part 3: HTTP Status Codes
Part 4: Result formatting
Part 5: Versioning
Exercises

Versioning

One of the first things you should think about when creating a Web API is how to handle versioning. However perfect you make your API, you're bound to find a way that's even more perfect before long, and then you'll need to launch a new version. If you haven't already planned out how your versioning should work, the lauch of a new version might be painful for the developers consuming your API. 
As RESTful APIs are growing in popularity and we see the number of SOAP APIs decreasing, my impression is that the focus on version handling is becoming better. Where developers previously put a number at the end of their method name, they now decide on an overall strategy for their API. 
Example: PayEx API
An example of the terrible "I'll just put a number at the end" versioning that arised with SOAP can be seen for example in the PayEx API. If we have a look at the PxOrder webservice, it contains the following methods: 
  • Cancel2
  • Capture5
  • Check2
  • Complete
  • Credit5
  • CreditOrderLine3
The developers consuming your API have no way of knowing whether the Cancel2 method is compatible with the Capture5 method, and this makes your API difficult to work with! 
So, what is the correct way of versioning your API? There isn't one. There are several possibilities, but there isn't 'one' correct that you should be using. Whichever way you pick, someone will claim that the one you picked is wrong, so pick the one you feel makes the most sense for your API. What's important is that a new version should not break the existing versions for the users of your API. 
Solution 1: URL versioning
Putting the version number in the URL is a quite popular approach. One of the APIs that does this is the Twitter API
GET https://api.twitter.com/1.1/trends/place.json?id=1
The upside of URL versioning is that you can quite easily change the structure of your API in the next version without breaking any changes for users wishing to stay with an older version. In addition to this, there is never any confusion as to what version of the API you are using, you can send the URL to someone else and they will see the same version of the API as you. The downsides to this approach is that you might have to maintain quite a large number of URLs as time goes by, and clients wanting to upgrade to a newer version will have to change all their URLs. Last, but not least, there is no way for the developers consuming your API to say: "Always give me the newest version of your API". Instead they have to say "Give me version X of your API".  
Solution 2: Query string parameter
Including the version number as an optional query string parameter makes it possible for developers consuming your API to always get the newest version. An API that lets you do this is the Netflix API
GET http://api-public.netflix.com/catalog/titles/series/7002352?v=1.5
Others prefer to use the date of the version release instead of the version number, for example FourSquare:
GET https://api.foursquare.com/v2/venues/40a55d80f964a52020f31ee3?oauth_token=XXX&v=YYYYMMDD
In both cases, leaving out the version query string parameter will result in the newest version being used. And creating a new version will never change the URL, only the query string parameter changes. This kind of versioning is great when the changes done from version to version are small. If there are any breaking changes from one version to another, and the users of your API are using the latest version, you might be breaking their code. "Breaking changes", get it?
Solution 3: Vendor Specific Accept Header

In part 4 of this blog series, we saw how we could use Content Negotiation with Accept headers for determining the result formatting. The same can be done for versioning, and it's often used in combination with result formatting in what we call "Vendor Specific Accept Header". The format for this is:
HEADER Accept: {type}/vnd.{company}.{version}+{type}

The GitHub API for example uses:
HEADER Accept: application/vnd.github.v3+json

This Accept header tells us that we want the results as application/json, and we're using version 3 of the API. By using Vendor Specific Accept headers, all URLs will be the same for any version of the API, which is good since one resource should only have one URL. However, there are some downsides to this approach as well. Changing the headers is not always a walk in the park, so it might make the API harder to use for some developers.
Solution 4: Custom Request Header

Instead of using the Accept Header as we saw in the previous example, some APIs create their own Custom Request Headers. An example is the Azure Storage Services API:
HEADER x-ms-version: 2014-02-14

The upside of creating your own Request header is that the version request header only determines the version. In our previous example of using a Vendor Specific Accept header, the type also had to be included. Again, all URLs will be indentical for any version of the API, but we still have the same issue of request headers not always being easy to modify.

Solution 5: All of the above?

If you're feeling really awesome, you can follow the example of Troy Hunt. He decided that since every type of versioning would be considered wrong by some, he would implement three different ones in his API to please the crowd. His blog post "Your API versioning is wrong, which is why I decided to do it 3 different wrong ways" is definitely worth a read!

Summary


Versioning is difficult as everyone has different opinions as to which way is the "right" way. What's important though is that you decide on a versioning strategy from day one so that it doesn't come as a surprise to you later when you decide to improve your API. Whatever you do, DO NOT break your clients code! And of course, care about your API from the very first piece of code you write.

Monday, September 1, 2014

How to create a Web API no one wants to use. Part 4: Result Formatting

Introduction to this blog series


Later this year, Netflix will be closing their public APIs. Twitter and Google have already restricted their APIs. Despite prominent tech-companies making drastic changes to their APIs, the number of APIs keeps growing steadily. Suddenly, everyone has a Web API. Your car has one, Chuck Norris has one, and worst of all, tech-companies with no focus on quality whatsoever has one. And who are using these APIs? Most likely, no one.
This blog series will take you through the pitfalls of creating a Web API. From a developers perspective, what mistakes will result in no one wanting to use your API?

Part 1: URI Design
Part 2: HTTP Verbs
Part 3: HTTP Status Codes
Part 4: Result formatting
Part 5: Versioning
Exercises

Result Formatting

The developers consuming your API will have varied opinions as to what format they want their results in. Supporting only XML might make developers who prefer JSON, JSONP or Turtle turn to other APIs instead of yours. In order to please the users of your API and to make sure you're not dictating the formats, you should support at least a few of the most common ones.

Example: Norwegian Meteorological Institute's Weather API

The Norwegian Meteorological Institute's Weather API provides forcast data for it's users. What we are interested in knowing is how they format their results. Let's ask for the sunrise data for Oslo, Norway:
GET http://api.met.no/weatherapi/sunrise/1.0/?lat=59.922086;lon=10.752844;date=2014-08-16

And we receive an XML result. According to ProgrammableWeb, XML is on decline and more and more API users prefer JSON (http://www.programmableweb.com/news/1-5-apis-say-bye-xml/2011/05/25). So APIs only supporting XML is decreasing in popularity:


Obviously, formatting your results only in XML is not a good idea then, you should also support other formats. So how are Web APIs out there doing that? Let's take a look at some of the different solutions:

Solution 1: URL extension

Some APIs let the user specify the format they want as a URL extension. I'm not a huge fan of this solution, but it's better than not supporting multiple formats so let's have a look at it.

In part 1 of this blog series, we had a look at the URI design of the U.S. City and County Web Data API. Let's ask for all links they have for Chicago, Illinois:
GET http://api.sba.gov/geodata/all_links_for_city_of/chicago/il

This request gives us XML in return. Now, let's ask for the same thing, specifying that we want the result in JSON:
GET http://api.sba.gov/geodata/all_links_for_city_of/chicago/il.json

We use the same URL, but we add 'json' as an extension. We can also add 'xml' as an extension and get the same result as we got when we didn't specify the format. In other words, if you don't supply a format extension, the fallback is XML.

The problem with using URL extensions for result formatting is that your API will have two different URLs that supply the same data. Having two separate URLs suggest that these are two different resources. However, they are not different resources, they are simply two different representations of one resource. So let's try another approach!

Solution 2: Query string parameter

A lot of APIs accept the format as a query string parameter, which of course solves our previous issue of having several URLs for the same resource.

In part 1 of this blog series, we analyzed the URI design of the World Bank API and as we saw then, they use a query string parameter to specify result formatting. Let's get all the countries:
GET http://api.worldbank.org/countries/all

As in our previous example, not specifying a format defaults to XML. So our request above is identical to:
GET http://api.worldbank.org/countries/all?format=xml

Now, if you want the result in JSON instead, you set format=json:
GET http://api.worldbank.org/countries/all?format=json

As you can see, each resource only has one URL and the different representations can be retrieved by including a query string parameter. But what if we don't want to specify the format, what if we instead want to say "These are the formats I support, give me one of them"? This can not be done with a query string parameter, and that brings us over to Content Negotiation.

Solution 3: Content Negotiation

Best practice when it comes to result formatting is considered to be Content Negotiation. Using Content Negotiation, the client tells the API which formats he is able to accept, and the API selects the first suitable format. Let's take a look at how the Facebook Graph API uses Content Negotiation. By default the API returns its results as text/javascript:
GET http://graph.facebook.com/daft-punk

However, if you want the result as JSON, you need to add an Accept header to your request:
HEADER Accept: application/json
GET http://graph.facebook.com/daft-punk

The Content-Type of the response will now be JSON instead as you've specified that you prefer JSON. You can add several formats to the Accept header. Let's see what happens when we add both JSON (which the API supports) and XML (which it doesn't support):


The Content-Type of the response is still JSON as the API picked the only format it knew it supports. Let's add another format to the Accept header, the text/turtle format.


In this request, we've added three formats to our request Accept header: application/json, text/xml, and text/turtle. The API only supports the first and the last, and therefore it picks the last one in the list.

By supporting Content Negotiation, you allow the users of your API to give you several options as to what result format to return. And that's how you make your API a walk in the park to work with.

Summary


When you're developing an API, it's important to remember that the users will all want different things and they all prefer different formats. There are several ways of letting your users specify the format they want, for example by using URL extensions, query string parameters or Content Negotiation via accept headers. There's a lot of discussion as to which of these is the "most correct", but what's most important is that you give your users a choise and care about your API from the very first piece of code you write.


Friday, August 29, 2014

How to create a Web API no one wants to use. Part 3: HTTP Status Codes

Introduction to this blog series


Later this year, Netflix will be closing their public APIs. Twitter and Google have already restricted their APIs. Despite prominent tech-companies making drastic changes to their APIs, the number of APIs keeps growing steadily. Suddenly, everyone has a Web API. Your car has one, Chuck Norris has one, and worst of all, tech-companies with no focus on quality whatsoever has one. And who are using these APIs? Most likely, no one.
This blog series will take you through the pitfalls of creating a Web API. From a developers perspective, what mistakes will result in no one wanting to use your API?

Part 1: URI Design
Part 2: HTTP Verbs
Part 3: HTTP Status Codes
Part 4: Result formatting
Part 5: Versioning
Exercises

HTTP Status Codes

When working with a public Web API, your greatest friend is Fiddler or Postman. Using those, you can debug your web requests and the responses given to you in return: 
The first thing any developer does when they issue a web request against an API is to check the HTTP Status Code of the request. Is the result a 200 OK? Yes, awesome! 
If you find pleasure in giving developers false hope, you should make your Web API return a 200 OK, even though the request was not successful. These types of "errors in disguise" will make developers flee from your API in no time. Saying "Your request was successful! ... Just kidding, gotcha!" is not a great way to attract users.  
Example: The World Bank API

In part 1 of this blog series, we had a look at the URI design of the The World Bank API. Let's go back to that API to see how that are handling their HTTP Status Codes. 
First, ask for all information they have on the country of Brazil: 
GET http://api.worldbank.org/countries/br?format=json 200 OK
As this is a valid request, all is good so far. Now, what happens if we specify a countrycode that does not exists, such as 'a'?
GET http://api.worldbank.org/countries/a?format=json 200 OK
That also returns a 200 OK, so maybe we were mistaken. Maybe 'a' is a valid country code afterall? Let's take a look at the response just to be sure: 
[{"message":[{"id":"120","key":"Parameter 'country' has an invalid value","value":"The provided parameter value is not valid"}]}]
Now, that's just mean. Let's try another one. What happens if we specify the format with a colon instead of an equal sign?
GET http://api.worldbank.org/topic?format:json 500 Internal Server Error
That's better, at least we're not given a 200 OK. We're given a 500 Internal Server Error, and they are even giving us a detailed outline of what is wrong: 
{"fault":{"faultstring":"Evaluation of script AssignQueryParamsCaseInsensitively.py (py) failed with reason: \"TypeError: cannot concatenate 'unicode' and 'NoneType' objects\"","detail":{"errorcode":"steps.script.ScriptEvaluationFailed"}}}
Problem: The World Bank API

The first issue here is that the API is returning 200 OK statuses despite there being something wrong with the request. The HTTP/1.1 protocol clearly states that 200 OK should be used when "The request has succeeded". 
The main issue, however, arises when we supply the incorrect format. The request produces a 500 Internal Server Error, although what really caused the issue was us supplying an invalid request. To make matters worst, the result contains a detailed error message. Displaying the internals of your Web API to the public makes it vulnerable to attack, and you should never ever return a stacktrace of the errors produced. 
Solution: The World Bank API

When you're developing a Web API, you should at least use the three most common HTTP Status Codes: 
Status CodeDescriptionFor dummies
200 OKThe request has succeededAwesome!
400 Bad RequestThe request could not be understood by the server due to malformed syntaxThe user of the API made a mistake
500 Internal Server ErrorThe server encountered an unexpected condition which prevented it from fulfilling the request.The creator of the API made a mistake
In addition to these, if you're serious about your API, you should also take a look at 201 Created, 304 Not Modified, 401 Unauthorized and 404 Not Found.
In the examples above, the request where we specified an invalid country code should have given us a 404 Not Found:
GET http://api.worldbank.org/countries/a?format=json 404 Not found

Specifying an invalid format should not have produced a 500 Internal Server Error, it should have given us a 400 Bad Request (without displaying its stacktrace):
GET http://api.worldbank.org/topic?format:json 400 Bad Request

Summary


HTTP Status Codes exist so that users of your API immediately know whether or not the request they made was successful. In the cases where the request was not successful, the status codes gives them a clear overview of why it failed. Disguising your errors as 200 OK's will only help in building up irritation, so you should consider using at the most common status codes when building your API. Also, do yourself a favour, and care about your API from the very first piece of code you write. 

Multiple CustomerContacts created in EPiServer Commerce

Creating a CustomerContact from a MembershipUser is something you'll run into quite quick when developing a Commerce site. Now, what's wrong with this piece of code?

public CustomerContact CreateUser(MembershipUser user, string firstname, string lastname)
{
   CustomerContact customerContact = CustomerContact.CreateInstance(user);

   SecurityContext.Current.AssignUserToGlobalRole(user, AppRoles.EveryoneRole);
   SecurityContext.Current.AssignUserToGlobalRole(user, AppRoles.RegisteredRole);

   customerContact.FullName = string.Join(" ", firstname, lastname);
   customerContact.FirstName = firstname;
   customerContact.LastName = lastname;
   customerContact.Email = user.Email;
   return customerContact;
}

To me, this piece of code looked fine until I ran it. What happened was that I received two CustomerContacts, one containing the correct information such as firstname, lastname and fullname. The other CustomerContact only contained the email address, nothing else. Both of them were linked to the correct account.

So what happened? Well, according to the EPiServer Commerce SDK we need to save the CustomerContact before calling AssignUserToGlobalRole"The CustomerContact associated with the user must be saved before calling this method. Otherwise contact information might be lost." 

In this case, contact information was not lost, it was duplicated. So what's the correct way of doing it then? We have to call SaveChanges on the CustomerContact before assigning the roles:

public CustomerContact CreateUser(MembershipUser user, string firstname, string lastname)
{
   CustomerContact customerContact = CustomerContact.CreateInstance(user);
   customerContact.SaveChanges();
   
   SecurityContext.Current.AssignUserToGlobalRole(user, AppRoles.EveryoneRole);
   SecurityContext.Current.AssignUserToGlobalRole(user, AppRoles.RegisteredRole);

   customerContact.FullName = string.Join(" ", firstname, lastname);
   customerContact.FirstName = firstname;
   customerContact.LastName = lastname;
   customerContact.Email = user.Email;
   return customerContact;
}

Thursday, August 28, 2014

How to create a Web API no one wants to use. Part 2: HTTP Verbs

Introduction to this blog series


Later this year, Netflix will be closing their public APIs. Twitter and Google have already restricted their APIs. Despite prominent tech-companies making drastic changes to their APIs, the number of APIs keeps growing steadily. Suddenly, everyone has a Web API. Your car has one, Chuck Norris has one, and worst of all, tech-companies with no focus on quality whatsoever has one. And who are using these APIs? Most likely, no one.
This blog series will take you through the pitfalls of creating a Web API. From a developers perspective, what mistakes will result in no one wanting to use your API?

Part 1: URI Design
Part 2: HTTP Verbs
Part 3: HTTP Status Codes
Part 4: Result formatting
Part 5: Versioning
Exercises

HTTP Verbs

There's an old story called "The Spider of Doom" where a company developing a content management system suddenly found that their client had "magically" lost all the pages of their website. After a lot of searching around, they found that the Googlebot was able to bypass their authentication mechanisms and had therefore crawled all their "Delete page" links. This, of course, resulted in all the pages of the website being deleted.

Imagine for a minute that you're creating a Web API that doesn't require authentication, but where the users should be able to delete content. You also want the endpoints to be crawled by search bots. How do you ensure that the bot doesn't delete all your content? Well, you make sure that any deletion of resources isn't done with a HTTP GET request. In other words, you use HTTP verbs in the way they were intended.

HTTP verbs makes it easy for other developers to consume your Web APIs without you having to manage and maintain several endpoints for each possible action. Sadly though, a lot of APIs only use the GET verb, and they use it wrong. On the bright side, that's a pretty great way of making sure no one will use your API!
Example: The Tesla Model S JSON API
I like to call the Testa Model S API the Batmobile API, and it pains me that I'm able to find something wrong with it. Tesla is only the greatest car ever built, and creating an API for it is genious, it only makes me want it more.
Let's start out by getting the current climate state of the car: 
GET /vehicles/{id}/command/climate_state
So far, so good. Remember, GET, PUT and DELETE are idempotent, meaning we can issue a request against them as many times as we want without changing the result. In addition to this, the GET method is safe, meaning it should not have any side effects or change state in any way. If we apply these two rules to the climate_state endpoint, we see that we can issue the request twenty times and we will always receive the climate state of the car in return, without changing the state of the car. So it clearly satisfies the criteria of the GET method.

Now, let's open the sun roof of the car:
GET /vehicles/{id}/command/sun_roof_control?state=open

Here we have a problem. When we open the sun roof of the car, we're changing the state of the car. Therefore, the sun_roof_control endpoint does not satisfy the criteria of the GET method.

Problem: The Tesla Model S JSON API

The main issue with this API is that it calls itself RESTful, but it uses the GET verb for all its endpoints except one. Had the API been implemented according to the HTTP protocol, then the following endpoint should have given us the current state of the sun roof, for example "open" or "closed". It should not change the state of the car in any way.
GET /vehicles/{id}/command/sun_roof_control

Solution: The Tesla Model S JSON API

In order to change the state of the sun roof, we should issue a PUT instead of a GET:
PUT /vehicles/{id}/command/sun_roof_control?state=open

The PUT method is not safe, meaning the request is allowed to change the state of the car. It is, however, idempotent. This means that the request above will always result in the sun roof being opened, whether we issue it two times or twenty. By using PUT, we're now satisfying the critera of the HTTP protocol.

What about POST and DELETE? Well, we can't delete sun roof, so the DELETE verb will not be supported. POST is usually used for creating items, and unfortunately creating a new sun roof is not allowed either.

GET (read)POST (create)PUT (update)DELETE (delete)
Returns the state of the sun roof (open/closed)Not supported, cannot create new sun roofChanges state of sun roof (open/close)Not supported, cannot delete sun roof

There is an extremely entertaining thread on Reddit about the Tesla Model S API and how honk_horn should have been implemented. I highly recommend taking a look at it!

Summary


If you're using the GET verb for all your endpoints even though state is changed, you will make developers using your API wrinkle their noses. Use the correct verbs for the job and you will see that maintaining your API will also be a lot easier. Also, do yourself a favour, and care about your API from the very first piece of code you write. 


Wednesday, August 27, 2014

How to create a Web API no one wants to use. Part 1: URI design

Introduction to this blog series


Later this year, Netflix will be closing their public APIs. Twitter and Google have already restricted their APIs. Despite prominent tech-companies making drastic changes to their APIs, the number of APIs keeps growing steadily. Suddenly, everyone has a Web API. Your car has one, Chuck Norris has one, and worst of all, tech-companies with no focus on quality whatsoever has one. And who are using these APIs? Most likely, no one.
This blog series will take you through the pitfalls of creating a Web API. From a developers perspective, what mistakes will result in no one wanting to use your API?

Part 1: URI Design
Part 2: HTTP Verbs
Part 3: HTTP Status Codes
Part 4: Result formatting
Part 5: Versioning
Exercises

URI design


If you're interested in creating a terrible Web API that will give developers headaches for ages to come and confuse them more for every piece of your API they use, you should start with your URI design. Badly named, inconsistent URIs that all violate the Principle of Least Astonishment will make your API just as disappointing as the movie "Mega Shark vs Giant Octopus".

Note: If you're building your API using hypermedia, these guidelines might not be applicable to you.

Example: U.S. City and County Web Data API

Starting out with an example, let's take a look at the "U.S. City and County Web Data API" created by The U.S. Small Business Administration.

Get all URLs they have registered for the city of Chicaco, Illinois:
GET http://api.sba.gov/geodata/all_links_for_city_of/chicago/il.json 200 OK

Assuming they use the same structure for all their endpoints, we can get all URLs they have registered for Cook Country, Illinois:
GET http://api.sba.gov/geodata/all_links_for_county_of/cook%20county/il.json 200 OK

So far, so good. What if I want to get all URLs they have registered for the state of Illinois? Based on their previous endpoints, this should work:
GET http://api.sba.gov/geodata/all_links_for_state_of/il.json 400 Bad Request

That didn't work. Which means that the developer using their API must head over to the documentation to figure out how it can be done, and the annoyance has already begun.

Problem: U.S. City and County Web Data API

The first thing to point out in this API is the terrible naming, which will at some point make this API difficult for the creators to maintain.

Using a structure such as all_links_for means you will end up with lots and lots of endpoints when the API grows. An example of this is already present in the API, where you should be able to retrieve not all links, but instead only primary links, which means all your endpoints will be duplicated:

http://api.sba.gov/geodata/all_links_for_city_of/...
http://api.sba.gov/geodata/all_links_for_county_of/...
http://api.sba.gov/geodata/primary_links_for_city_of/...
http://api.sba.gov/geodata/primary_links_for_county_of/...

Imagine what happens when they want to be able to give you broken links or secondary links, they will have to duplicate their endpoints for each new type of link, which in the end will be impossible to maintain.

The second problem with this URI structure is that it is not logical. As a developer, I am not able to predict what the URI of the next endpoint I'd like to use is based on my experience with the other endpoints.

Solution: U.S. City and County Web Data API

One of the many alternative ways this API could have been implemented. The pros of this implementation are:
  1. The URIs are readable and simple to understand
  2. The URIs are hackable, meaning I can remove the last part of the URI and still have a valid request.
  3. Querystring parameters are used for filters, so you don't have to duplicate all your endpoints when you'd like to add a new type of link.
Get all links for the state of Illinois:
/links/il

Get all links for Cook County, Illinois
/links/il/cook%20county

Get all links for Chicago, Illinois
/links/il/cook%20county/chicago

Get all primary links for Chicago, Illinois
/links/il/cook%20county/chicago?type=primary

Example: The World Bank API

Let's have a look at another Web API, The World Bank API. First, get all topics and indicators respectively:
GET http://api.worldbank.org/topics 200 OK
GET http://api.worldbank.org/indicators 200 OK

That looks like a pretty decent API, right? It's simple and it's logical. Now, let's get the topic with ID=5, and then get the indicators for this topic:
GET http://api.worldbank.org/topic/5 200 OK
GET http://api.worldbank.org/topic/5/indicators 404 Not Found

Ah, damn it. Logic no longer applies. In order to get all indicators for topic with ID=5, I can no longer use the plural name for indicator, so let's try with the singular name:
GET http://api.worldbank.org/topic/5/indicator 200 OK

Awesome, inconsistency!

Problem: The World Bank API

This API is not actually that bad, there are a lot worse of there. It follows many of the best practices out there, such as using nouns instead of verbs and having a logical structure.

However, the inconsistency between plural names (indicators) and singular names (indicator) strictly violates the Principle of Least Astonishment and makes the API inconsistent.

Solution: The World Bank API

Stick to plural nouns all the way in order to make the API consistent.

Get topics:
/topics

Get topic with ID=5:
/topics/5

Get indicators for topic with ID=5:
/topics/5/indicators

Summary


Badly named, inconsistent URI designs will not only be a pain in the arse for the developers using the Web APIs. They will also turn out to be a pain in the arse for the developers maintaining them. So do yourself a favour, and care about your API from the very first piece of code you write. 

Monday, August 11, 2014

How the media sexualized the story of a 16-year old girl in tech instead of acknowledging her work

Imagine you're a journalist. And you've been told to write a story.

You've been told to write a story on the winner of the 2013 Science in Action award. The winner is Elif Bilgin, a 16-year old girl from Turkey. The award is part of the Google Science Fair, and the title of her project is: "Going Bananas!-Using Banana Peels in the Production of Bio-Plastic As A Replacement of the Traditional Petroleum Based Plastic".

What do you do? Well, let's sum up the keywords: Bio-Plastic. Female. Google. 16-year old. Petroleum. Award winner. Tech. 

It sounds like a pretty great story, doesn't it? I think so. As a journalist, you have the chance to write a story that will inspire other youngsters who are interested in science. You have the chance to show the world that young girls with great ideas can be seen, acknowledged and appreciated for what they are doing. You have the chance to tribute women who are interested in technology.

Or, you could look at the story and think: Here's a girl working with bananas, I think we need to sexualize this. And that is exactly what the reporter at metro.se did when he wrote an article on the subject last week:


In english, the title reads: "You can never imagine what she can do with a banana". So, instead of attracting readers who would be interesting in reading about the great accomplishments of a 16-year old girl, the author decided to attract a completely different audience by sexualizing the article.
This pisses me off. First of all, the girl is not even an adult, she should not have to deal with men drawing parallels between her work and sex. Second of all, what she has done is incredible and the journalist shows no respect for what she has accomplished.

As a woman in tech, I glow with pride whenever I see other women do something that might attract even more women to our industry.

When I was younger, my mother would save any newspaper articles for me that could inspire me to pursue my dreams. I loved reading about other teenagers, both male and female, researching topics that could make a difference. Elif Bilgin would have been a true inspiration to 16-year old me, even more so than she is now. Would my mother have saved this newspaper article for me though? No, I don't think so. I think she would have wanted to spare me the insight of how some men decide to view women in tech.

I hope this journalist has learned his lesson. And the next time he gets the chance, I hope he decides to show the world that young girls with great ideas can be seen and appreciated for what they are doing.

If you'd like to read a serious article on Elif Bilgin's project, I recommend taking a look at this blog post from Scientific American.

Note: Metro.se decided to change the title of the article after receiving numerous complaints. You can read the article here.

Tuesday, July 1, 2014

Beginning research on Ole-Johan Dahl and Kristen Nygaard

Today is my first day of summer vacation, so I decided to take my son to the informatics library at the University of Oslo to see if I could find some reading material on the work of Ole-Johan Dahl and Kristen Nygaard.

Exciting summer reading
These guys invented object-orientation in the 1960s as they created the Simula programming language. What I'm interesting in finding out is how they came up with object-orientation, and the effect this has had on the world of computer science. In order to to that, I'll probably have to dig deep into their work and Simula.

The amount of relevant material the library had was beyond my imagination! They have recordings and scriptures of many of their lectures, they have Ole-Johan Dahls archives from when he worked at the university, they were able to give me a list of people at the university they worked with and who I can interview. Best of all, they gave me a list of people who are doing research on similar topics. To sum it all up, that place is a gold mine! And I have a feeling I will be spending some time there in the future.

I brought some books home so now my summer reading is covered:
History of Nordic Computing 1-3
History of Programming Lanaguages
Object-Oriented Programming with Simular 
Simular Begin
Common Base Language

I'm really excited about that last one, "Common Base Language" (commonly known as Simula) as it is written by Ole-Johan Dahl, Bjørn Myhrhaug and Kristen Nygaard in 1970. Awesome, huh?


  

Monday, June 30, 2014

When you're not allowed to translate blocks in EPiServer 7

If you find yourself not able to translate blocks in EPiServer 7, you might not have marked the language you're working with as available. 
The block you want to translate will look like this, as you can see the translate button is disabled. 



How to set the language as available: 

1) Go to the startpage

2) Click on "Tools" -> "Language settings":












3) Select the language:

















Now, if you return to your block, you'll see that the translate button is enabled and you can translate the block: