Sergio and the sigil

Language Envy - hash literals

Posted by Sergio on 2009-01-05
Language Envy: This post is part of a series where I wish C# had a particular feature I came to like when working with other programming languages.

It's easy to let a small language feature go unnoticed. The more I spend time writing JavaScript and Ruby, the more one little detail shows itself loud and clear when I go back to my trusty C# (well, it shows itself by not being absent, if that makes any sense.)

The little language detail I'm writing about today is the literal syntax for hashes. Especially in JavaScript, because all objects are just hashes on steroids, which makes the literal object syntax become one and the same with the hash literals.

In JavaScript it's easy as 1-2-3. It's not surprising so many libraries are adopting hash parameters.

//Prototype.js sample
var elements = { success: 'myDiv', failure: 'errorDiv' };
var ajax = new Ajax.Updater(
	elements, 
	'getData.aspx', 
	{ method: 'get', onFailure: reportError }
	);
//jQuery sample (jQuery UI)
$('#fromDate').datepicker({rangeSelect: true, firstDay: 1});
$("#search").autocomplete("/product/find",
	{ autoFill: true, delay: 10, minChars: 3 }
	);

Now, I understand that part of the popularity of hashes in JavaScript and Ruby is due to the loose typing of these languages. But if the syntax wasn't light, APIs like the above ones would be much more painful to use.

C# 3 does have a hash syntax (or, more accurately, a dictionary one.) Unfortunately, dictionary initializers, although being a step forward, still leave noise to be removed.

// hypothetical search API 
var books = FindWithCriteria<Product>(
              new Dictionary<string,object>
              {
                {"Category", Category.Books},
                {"MinPrice", 33.45},
                {"MaxPrice", 50.00},
                {"Contains", "asp.net"}
              });

Hmmm, no, thanks. Maybe that's the reason we are starting to see some APIs that use (abuse?) anonymous objects and reflection to create hashes.

// hypothetical search API 
var books = FindWithCriteria<Product>(
              new { 
                Category = Category.Books,  
                MinPrice = 33.45,
                MaxPrice = 50.00, 
                Contains = "asp.net" 
              });

This last one doesn't look so bad on the surface, but we know what is going on under the covers so it's like putting lipstick on a pig. If, instead of using reflection at run-time, the compiler had support for converting the above anonymous object into a IDictionary<string,object>, then we would have a more convenient and efficient way of creating hashes. Maybe it's too late to introduce a feature like that while maintaining backwards compatibility.

I believe when you add a language feature that is elegantly designed (i.e. clean and unnoticeable,) it becomes popular more quickly — just like what is happening with lambdas . The existing alternatives for creating hashes in C# 3 are still too noisy or inefficient to be integrated in our code without reducing the readability or incurring a performance penalty.

Language Envy - episode 0

Posted by Sergio on 2008-12-24

Although C# is the language that I can call myself proficient enough to make a living these days, there are other languages that I have to use for specific tasks (like JavaScript, SQL, XSLT.) I also like using other general purpose languages for pure exploration or pet projects. I'd include Ruby, ObjectiveC and PHP in this group.

When using other languages it often happens that I encounter features that I wish C# had or that the C#-equivalent was as easy (it works both ways — I miss some C# feature on the other side as well.)

In this series of undetermined length I will be posting some of the items from my wish list as I remember them.

The case statement

To start things off, let's check out C#'s case statement, straight from the language specification.

switch-statement:
    switch   (   expression   )   switch-block
switch-block:
    {   switch-sectionsopt   }
switch-sections:
    switch-section
    switch-sections   switch-section
switch-section:
    switch-labels   statement-list
switch-labels:
    switch-label
    switch-labels   switch-label
switch-label:
    case   constant-expression   : // <-- line 14
    default   :

I know that doesn't look like C# code. What I'd like to point is in line 14. The expression in each case label has to be a constant. I'm sure that helps making the switch statement compile to a very efficient MSIL code, but let's consider what we are missing because of that.

Here's a sample of what you can do in a Ruby case expression.

SIDE NOTE: The hawk-eyed reader will catch the terminology difference here. Many language constructs that are mere statements in C# are expressions in Ruby. But that's not the feature I'll write about today. Maybe in a future installment.
Months = %w(JAN FEB MAR APR MAY\
        JUN JUL AGO SEP OCT NOV DEC)

def get_month(value)
  case value
    when Date # class name (instance of?)
      return Months[value.month - 1]

    when /\d{4}-(\d{2})-\d{2}/ # Regular expression (matches ?)
      return Months[$1.to_i  - 1]

    when 1..12  # Range of values (contained ?)
      return Months[value - 1]

  end
end

puts get_month(Date.today)
puts get_month("2008-10-20")
puts get_month(8)

As you can hopefully see in the above example, the expressions in each when statement do not need to be constants (class names like Date are constants, by the way)

Ruby defines the === (triple equal) comparison operator that can be overriden in each class and is used in the case expression to test each when condition. This is usually read as "when value matches with this expression here...".

Not surprisingly, the built-in classes in Ruby do override the triple equal operator to add a more meaningful implementation for it. Range matches the values that are within the range. RegExp matches values that agree with the regular expression, Class objects match values that are instances of that class, etc.

I use this feature all the time and it's so convenient that I'd be thrilled to see it in C# one day.

So, what is my suggestion?

I wouldn't be a real programmer if I didn't try to sell my own suggestion, would I? Since IComparable is taken and means something different, I was thinking of maybe something like this.

public interface ICanMatch

Transitioning - part III - enter the learner

Posted by Sergio on 2008-09-11

Turning the table

So here I am, the guy often in charge of assisting new developers get up to speed with my designs and code, facing the diametrically opposite situation.

Like many other developers, I have changed jobs more times than I'd like to. I love the chance to learn from a new industry or platform, I just wish the transition wasn't as traumatic as it frequently is.

I've seen developers hit the ground running, but I've also seen other developer struggle and run in circles not knowing how to proceed when faced with the new environment.

I believe each place has its own challenges but it's still possible to follow some guidelines (or more like heuristics) to optimize the whole ordeal.

Humility - leave that big ego at home

This may be sad news to you, but it's probable that you'll be facing several brick walls. That has nothing to do with your skills or how great a problem solver you are. It doesn't matter. The environment is new to you, possibly the business itself is completely foreign too.

So ask! You will not be perceived as incapable just because you ask too much. Yes, at least try to solve the problem, but don't go thrashing for hours and hours. You have too much too learn and not a lot of time.

Identify the key players

Maybe you will be introduced to the team in you first day and tons of job titles will be thrown at you. Don't spend too much energy trying to remember who has what position in the org chart.

More often than not, these titles have very little to do with the actual role each individual plays in the team or project. Just because someone is labelled senior developer it doesn't mean that that person's contribution will be more effective or regarded than that lowly intern that is on a Summer job or even somebody not directly in the team, like a business user.

Knowing who really has the information you need should always be one of the priorities in your first week at the job.

Identify the real mentors

You know how that is, someone gets the task of being the assigned target for your questions or for pairing with you for a tour of the system. What may not be obvious is that your assigned mentor may have been appointed and not volunteered for that task.

It's possible that there are other members in the team with more inclination for mentoring or that is better at explaining things. So why was not that person chosen to be you mentor? Who knows... Too busy? He/she was on vacation when you started? Bad management? It's uninportant. It happens. It sucks.

Bottom line, disregard the assignments and go for the gold. Once you discover the mentors in your new team. Jump at them. The real mentors will be happy to make themselves available to assist you.

Pick your battles - everybody has defects

The temptation to point out problems is ginormous when you start. It's understandable. You want to show something you know, to contribute, to become valuable, etc.

The unnecessary risk in that is putting yourself in an antagonistic role. It's hard enough being the new guy. Being the guy that came to make us look bad is definitely undesirable. The system had those problems before you got there, chances are nothing serious will happen if you wait a little longer to understand the ground you're stepping on.

Unless you were brought in specifically to review or address a particular problem, exercise your best judgment and don't stick your finger at every little flaw. Everybody has shameful code in their source control log.

Learn the business, talk the talk

New job invariably brings a different way to do business, maybe a new industry altogether. We will do a huge favor to ourselves if we make an effort to learn this new business. Learn the jargon, learn the business model, learn why your end users are using the software, learn about the competition... Learn.

In any semi-serious shop, just knowing the business lingo should give you a head start in understanding even classes and table names in the system. Not to mention you will be able to sustain a decent conversation with the business stakeholders more quickly.

Jump at the opportunity

To top it off. I've seen these countless times, and it still saddens me. Everywhere you go, every team, every project, there's tons of stuff that could be better if someone dedicated some time to it. Unfortunately the lack of initiative is a plague that affects not only software development but pretty much every field. It probably had more to do with sociocultural roots than being a bad professionals.

How many times you've heard complains or suggestions flying by in team gatherings along the lines of: "Have you guys ever used a wiki? It would be cool if we had one", "Our [ bug tracking | source control | logging component | 3rd party controls library | insert pet peeve here ] sucks, I wonder if there's anything better out there", "We seriously need to take the time to document this API", "I hate doing this every time. This should be automated". Let's try not to look at these statements as merely problems or chores that represent the status quo and be prepared to deal with them. In reality these are examples of opportunity. Things that nobody in the team likes or knows how to do. More importantly, many of these can have a direct impact on how well things work, more than it may be apparent. Oh, that's right, they can be fun too.

Transitioning - interlude

Posted by Sergio on 2008-09-04

Right after I mildly complained about the lack of thoughtful orientation on a new job, I was pleasantly surpirsed with this lovely schedule for my first week at the new place.

Just wanted to share that with you. There's hope for our world.

Transitioning - part II - oh, the expectation

Posted by Sergio on 2008-08-31

Nothing like a long 3-day weekend to help forgetting about the old problems from your previous job. This should help making room for the upcoming avalanche of new information and ramping up on the new gig.

Show me where the North is

I'm also taking this short interval to revisit my previous experiences of changing jobs and what waited for me on my first few days. I think that in all the other transitions only once there was an orientation process in place to assist the new guy learning the ropes. The common approach has always been to give a brief half-day or less introduction to the system, show how to get the source code, show the database diagram, meet your team leader, webmaster, DBA and manager, then go fix some bugs or build a prototype of a new feature.

I can't say that style of orientation (or shall we call it hazing?) can't work. It may work for some types of developers and worked for me, but it's risky and painful. It's also fuel for misunderstandings and propagation of myths. I won't lie and say that I could completely understand the entire system just by reading the source code and outdated documentation, it often happened that I had to grab any chance I had with more senior team members to ask questions that other developers in the same situation as myself could not answer.

The phases of a new job

a.k.a.: From "what the..?" to "yuck" to "a-ha!" to "this is great" to "this can be better"

I wanted to write this before I even look at the source code that waits for me because I don't want my new team mates thinking I'm talking about their master-piece. Again, I'm referring to my previous job/client changes.

One thing that invariably happens with me when I start reading unfamiliar source code is that shock of dealing with different coding styles, different coding standards, different 3rd party libraries, and sometimes different programming languages (or versions).

A lot of the discomfort is caused by superficial issues like naming conventions that temporarily obscure the understanding of the important characteristics of the system. We shouldn't be distracted by these conventions or code formatting style. What we are really trying to understand and get up to speed with is how the product was designed and which are the important components and identifiable patterns we need to adopt. It's okay to start off writing code with disagreeing naming styles, these things are easy to fix. Misusing or not using the design principles applied in the rest of the code is way more costly to fix, demanding more careful refactoring.

Once we start to see through that noise, we will finally be able to understand the why's and how's of the system. With that understanding comes an increasing sense of admiration for the code. I'm not saying that you will agree 100% with what you see, but at least you can feel more confident that you know what you're stepping on.

With that confidence in place we can start to identify places in system where cracks can start to show or more appropriate solutions for some of the issues. In general, we start to be able to contribute more than just code, but also design options.