Monday, August 15, 2011

Should You Unit Test Interaction with Static Methods?

No. You should not. Here's an example:


If you are somehow mocking this static method, you are potentially making it dangerous for other places where this static method is used. Eventually, this will create red test results that are hard to find and make your tests dependent on each other.

Tuesday, August 09, 2011

Should you unit test methods with a lot of mocking?

Well, anytime you have a lot of mocking, it is probably a smell. Particularly, a first smell is violation of the law of demeter. However, we were having discussion about whether or not we should write unit test for something like the following example:



As you can see, this method actually does a quite important task. It invokes the search method with specific parameters that will determine your search results. Now, we were debating whether or not the example unit test actually brings any value.

Here's what we have discussed:
Pros:
It confirms that you are actually calling the third party method with the right parameter.
Cons:
The test is too tightly coupled with the implementation, so it will break if something changes inside the method irrespective of its actual output.

But we failed to come to an unanimous decision on its usefulness. We all agreed on the point that it definitely needed some integration tests to make sure the search had actually worked.

Here are two questions for you:

  1. Would you skip the unit test altogether for this method and rely completely on an integration test? Why/Why not?
  2. If you are to rewrite this code, how would you write this using TDD?

Looking forward to see your input on this!

Friday, August 05, 2011

Ruby present? Method

Ruby has a nice little keyword called unless, that checks the opposite of if. So, you are probably used to a code like this:

return customer.first_name unless customer.nil?

If you haven't used present? before, you can in fact turn the above unless into a more familiar and easy to understand if statement:

return customer.first_name if customer.present?

So, in most cases when you are using unless with a negative condition, you can use present? and if instead. I find it way easier to read.

present? does the opposite of blank?. So, you will get the following:

nil.present? #=> false
[].present? #=> false
"hello".present? => true
["a"].present? #=> true
Hope it helps!

Tuesday, July 26, 2011

Constructors Are Methods, too!


Yes, if your constructor does something meaningful. This is just like another method and should be treated equally for unit testsing purpose. Here's an example that should need unit test:

It looks simple, so testing it should be simple, too. I would only skip the default constuctors, as long as they don't do anything interesting.

Friday, July 22, 2011

How to Annoy Your Customers? Learn from GoDaddy Account Status Email

Just looking at this screenshot alone, what do you think it is?
I have a few domains registered with GoDaddy. I went with them, because at that time, I didn't know of another renowned provider. But they have always been the best of producing the most confusing ever user interface. The account status email is one step ahead in that same direction.

This is how it starts:

At the top right corner, it says July 2011, in grayed out font! A deliberate attempt to de-emphasize the statement period!

Just below the date, there is a fake input box and a button labeled Go. This is an image and if you click it, it will actually open a new page instead of asking for user input right inside the search box. This is just following the theory of most surprise (as opposed to principle of least surprise)!

Next, in red background, they welcome me by saying, Welcome, S. M. Sohan! Customer Number: ### wtf? Customer Number? Do I give a shit what my customer number is? Why is the welcome grouped together with search and contact? How are these related?

Then it says, Log in to your account on our secure website to view your most recent account statement. What does this mean? Does it mean, this statement is not recent? Is this not secure?

Then it says, Summary of your account as of 7/21/2011**. That f'ing footnote will tell you that, the information may not reflect recent changes! What? Is this good enough till 7/21? If not, why do you even send this bullshit to me?

Then it has 4 boxes side by side. The first one, Messages has Alerts: No, Notification(s): Yes. View now is a button to their site. How stupid is this? Why bother saying alerts "No"? If you know I have notifications, why not put it right here? Why are you confused about notification"(s)" - you should know if its just one (notification) or more (notifications). How lazy is that?

Items Expiring is the other funny one. It says, Domain names: No. Then it says renew now. What? You're saying nothing is expiring. Why on earth I would renew something?

Then it takes almost 50% of the screen for asking me to contact with them through a number of channels including Facebook. Really? Facebook fan of GoDaddy? Crazy people!

In the end, they don't care putting a note of thanks, let alone personalize it with the name of an actual person. Isn't it rude to end an email this way?

Now, with all these hammerings - as if it fell short of creating enough fun, it says, More for You: followed by tens of fine print links to things that don't matter at all to me. Oh boy! you are awesome!

I am not a designer by any means. However, I think, even I can design a better version than this crap. Here's my version in a screen mockup.






Monday, July 11, 2011

Avoid Duplication in Config Files

Any kind of configuration file, be it an ugly xml file or a prettier yml or properties file, its been a source of frustration to me. Here's a list of few such pain points:

  1. There are two config keys that point to the same value. e.g. db_username=master, data_source_user=master
  2. There are two config keys for urls that point to the same domain, but different paths. e.g. market.com/cameras and market.com/undies
  3. Config entries with placeholders. e.g. weather_url= weather.com/%s or weather_url= weather.com/%s/hourly
  4. Config entries with default values that should not default to anything.
  5. Config entries that are required but don't fail the application deployment when not set.

Are you having to deal with similar pain points? Some more?

Saturday, June 25, 2011

How Not To Provide Feedback When Doing Code Review

Code review, as any other review process, can often be an attack on someone's ego and incite anger and frustration. Being both on sending and receiving end of such code reviews for years, I have learned a few how-not-to-do-it, or as one might say, anti-patterns of providing code review feedback. Let me know if you agree/disagree with me on the following:
  • You are always reviewing Adam's code while Adam is never reviewing yours.
  • Your feedback is like "Adam, you should break down part of this method into a private method" instead of "we can probably extract a part of..."
  • You are always suggesting, for example "we should do x and y and z", instead of asking interesting questions "can we do x? what if we did y?"

Wednesday, June 22, 2011

Service API and Exceptions


Too often I see I am using a REST/SOAP API to talk to a third party system that frustrates me because of poor error messaging. Here's an example to illustrate a typical frustration:

Call: city_service.update_residence_address(city_dueler, new_address)
Response: <status>Failed</status><error>Invalid address</error>

But the address just seems right to me. So, I need to know specific reason about why the address is wrong. The error message leaves this critical detail. What happens next is, I look for the log files created by the city_service, conceptually supposed to be a third party hosted service. To do this, I SSH to the server, then cd to the logs folder and get lost in many of the cryptic log files. Then eventually I find a log and if I am lucky, I find something like the following:

InvalidAddressException at:...
...
Street number is not listed..
...

Now, I know I had an issue with the streer number. But I can see this only after I looked into the log of the thirdparty server. In an ideal case, I don't have an access to their server. Even if I have it, I cannot easily understand their logs and stack traces! In most API calls to third party applications I have had this frustration to varying degrees.

Here's a lesson learned:
Next time you expose an API for another app, expose error messages as specific as possible - so that, no details is left buried into your log files.

Thursday, March 17, 2011

NuGet - Why Should You Care?

Traditionally the .NET community, or more appropriately the users of .NET framework relied on products from Microsoft - so, in a product stack you are likely to see almost everything coming from Microsoft. However, some community contribution made its way into the main stream - for example, NUnit or Log4Net. But you can literally count the number of such main stream non-Microsoft products in your development stacks with your fingers (sparing a few)!
NuGet makes it easy to share your reusable library/utility code to the community. So, if you've done something cool that you wanna share, you should utilize the platform.
One important difference between your and Microsoft's contribution is, whatever you are contributing is likely to be a piece of software extracted from one of your real world projects. On the other hand, Microsoft attempts to produce something based on public interest and their imagination - often missing the real pain that you or I have. So, this mismatch between the designer and the actual consumer of the product often leaves a lot of opportunity for you. If you did something to solve your own pain on a project, its likely you're not alone. So, share it with us.
NuGet official feed and website is a great place to get feedback.
Did something cool? Well, you should feel good as people will use and appreciate your work. More importantly, they will provide you with interesting ideas and reviews that you haven't thought about. Does this sound useful to you? People will go even further - they will directly contribute to the project with code!
NuGet will challenge you with competition from other contributors.
A healthy competition is a great way of learning from others too. You'll see other contributors attacking the same pain you are solving in a different approach, often directly challenging you! You love challenge, don't you?
If you need hard numbers to get motivated, here's some data from my MvcMailer project:
  • Downloaded 600+ times in less than 2 months.
  • Received 60+ emails from people using MvcMailer, mostly encouraging feedback.
  • 300%+ increase in my blog traffic.

Bottom line is, you should publish your NuGet package if there's any cool project you have done. Or, look out for what others are doing and possibly contribute with your code/suggestions. If you need an idea, look for StackOverflow questions, you'll see there are solvable problems that people are fighting against time and again.

Monday, March 14, 2011

My 2011 Q1 developer roadmap

For me, 2011 Q1 has so far been a good exposure to new techniques, tools, articles and books, thanks to ThoughtWorks book allowance! However, if you are interested, here's what's keeping me busy:
  1. User Experience: I find a good user experience is THE thing that you want in anything you design, and if you are writing a software, its even more important. After I read a few books, I have a feeling that its not just a common sense approach, it takes some education and a deep care to produce something usable. Check out my reading list at http://smsohan.com
  2. HTML5: HTML5 is so more than just knowing How To Meet Ladies (HTML)! The popular browsers are all way ahead of the official HTML5 release date, so if you are building something on the web, its time you give it a real shot. Again, I shared my reading list on my website.
  3. .NET NuGet: Microsoft .NET just got a major component, NuGet package manager, that greatly simplifies the sharing and consuming of reusable libraries. Already there are tens of thousands of downloads for the popular .NET libraries and I believe its just a start. So, if you've done something cool in your project and want that to share with the .NET crowd, you should consider NuGet as a distribution channel and get some traction on it.
  4. MvcMailer: MvcMailer has got all my developer attention in the recent past. If you haven't checked already, I highly encourage you take a look at its features at this page and you'll see its a full stack elegant emailing solution that you need in your ASP.NET MVC projects. However, while working on this, I got familiar with the internals of the ASP.NET MVC source code and I consider this as a good experience.
  5. Functional Programming: Did you learn one? Which one? Please suggest me your favorite functional language. In the remaining of this Q1, I want to spend some time on a functional programming language, probably F#.
Its inspiring to see Calgary getting warmer these days - hope we get some outdoor soccer by the end of 2011 Q1, that would be awesome!

Monday, March 07, 2011

MvcMailer 1.0 Released

Just released MvcMailer 1.0 as promised in my previous post. Download your copy using the following:
Install-Package MvcMailer
Of course, you will find a comprehensive tutorial at: this github wiki page.

Friday, March 04, 2011

Whats Coming in MvcMailer NuGet 1.0?

Thanks to 365+ downloads of the MvcMailer NuGet before it hit version 1.0 and now its time to wrap up the NuGet package for an official first release. I got several encouraging feedback on this package and here's what you get from this first release:
  1. Use Scaffold Mailer to generate your mailers with views.
  2. Compose rich emails using your favorite ASP.NET MVC view engine.
  3. Use master pages and pass data using ViewData/ViewBag.
  4. Send multi-part emails for both text and html email readers.
  5. Put images inline so that they are visible even when email client is offline.
  6. Write unit test for your mailers and controllers that use the mailers.
  7. Send attachments.
  8. Send emails asynchronously.
To my knowledge, MvcMailer is gonna be the first full stack ActionMailer like Emailing library for ASP.NET MVC 3. If you are an ASP.Net MVC programmer who deeply care about high quality work and maximizing efficiency - you gotta try MvcMailer 1.0 for writing pretty email sending code.
The github wiki page has everything you will need to know about MvcMailer. Version 1.0 comes out on Monday. Stay tuned.

Friday, January 28, 2011

ActionMailer 3 - why do you call instance methods as class/self methods?

I didn't even notice this little trick! As long as I didn't have to call deliver_welcome_message (or deliver_*) methods that would magically call welcome_message, I was happy that now the magic is gone. Things are transparent!
Here's an example showing the change: Say you have the following mailer:
class Notifier < ActionMailer::Base
  def welcome_message(new_user)
    #a warm welcome message
  end
end
Now, prior to Rails 3, or ActionMailer 3, you would write the following to actually call this method to get the benefits of ActionMailer magics, such as finding the view based on method name and so on:
Notifier.deliver_welcome_message(new_user_instance)  
I am sure this deliver_* was a clever design decision to solve a hard problem, that is, finding the view name based on the method name. However, in ActionMailer 3, this is gone. Now the question is, if this trick is gone, how come it still finds the view name from the method name? Who sets the view name? To know the answer, first, let's take a look at how we call the welcome_message now.
Notifier.welcome_message(new_user_instance).send
Instead of

Notifier.new.welcome_message(new_user_instance).send

So, the magic deliver_ prefix is gone. But, did you see the new trick? Well, its a clever design again. The trick this time is, you call your instance method, welcome_message as if it was a class method. But there is no class method called welcome_message, so it instead goes to method_missing and thats how it sets up the view name from this call. Here's the code that does this little trick!
def method_missing(method, *args) #:nodoc:
    return super unless respond_to?(method)
    new(method, *args).message
  end
All it does is, instantiates the mailer with the method name!

However, this design decision has interesting side effects as well. Or may be not side effects, but rather core effects. For example, since you are calling your mailer methods as class methods, you cannot use a single mailer instance to send out multiple emails at the same time. In fact, every mailer has only one instance of message. So, it cannot store two messages at the same time. This is as if, you can have multiple methods in a class, but you cannot call more than one class or you will mess up the class's state!

Wonder why? Well, this is rooted in another key design choice: ActionMailer::Base is a subclass of AbstractController::Base. Now, if you look at controllers, you will notice that at any given point of time, a controller instance is only responsible for responding to a single action. This is logical for controllers. But how about mailers? I see a mismatch in my mental model and the actual implementation model. I don't see a reason why a mailer is a controller! For the sake of code reuse? But that could be done via delegation anyway.

I will end this post with one question:
Do you think mailer is a controller? hints: think about LSP.

Friday, January 14, 2011

Social Helpers in ASP.Net MVC3 (Facebook, Twitter, Gravatar etc.)

This site shows the examples!
http://www.asp.net/webmatrix/tutorials/13-adding-social-networking-to-your-web-site

Now, the social links and buttons are no longer from a third-party source, its straight from Microsoft. I don't know if this is first-party or second-party :p

Thursday, January 13, 2011

My Article at CodeProject: MvcMailer

I just released a .Net NuGet package called MvcMailer and to get people super easily started, put an article at CodeProject.com. You are most welcome to the article at http://www.codeproject.com/KB/aspnet/MvcMailerNuGet.aspx
I welcome your comments and suggestions!

Friday, January 07, 2011

C# Named Parameters Can be Very Useful

Think about the following code example:
htmlHelper.InputHelper(InputType.CheckBox, name, "true", true /* useViewData */, false /* isChecked */, true /* setId */, false /* isExplicitValue */, htmlAttributes);
This line is taken from the source code of ASP.NET MVC, or to be more specific its a line from the InputExtension class. I think the intent of the original developer is clear:
Add comment next to arguments so that one can easily read the method call without getting lost in a who's who since there are quite some arguments to pass.
To learn more about named parameters using C#, you can visit this post by ScottGu.

Sunday, January 02, 2011

2011: Yet Another New Year

Dear Readers:
Happy 2011. 2010 was a great year. Why?

  • Defended my MSc thesis after a moderate 16 months of grad school life.
  • Published 3 papers in 3 international conferences.
  • Visited 4 new countries - Netherlands, Sweden, Finland and Norway.
  • Visited a few interesting cities - Vancouver, Victoria, Edmonton.
  • 100+ posts on DrinkRails.com.
  • 25,000+ visits to my two blogs from all over the world.
  • Developed a fresh new app, Plexina Central, for Wairever Inc.
  • Lived a healthy life.
  • Bought my first (98 Corolla) and second (2000 CR-V) cars (also sold my first car)!
To live up to this standard, 2011 is surely challenged by 2010. Let's see how 2011 rolls: To give you a heads up, I am joining ThoughtWorks as a Consultant on January 4th!
However, 2010 was the only year in my life when I didn't see my parents and siblings. I hope, 2011 does a better job in this regard. It is getting essential now.
This is how I look at the close of 2010
And I want to look leaner at the close of 2011 or even before that :(

Monday, December 13, 2010

DRY - Total 161 Duplicate ArgumentNullException calls in ASP.Net MVC Source Code

There are 161 occurrences of the following code pattern inside the ASP.Net MVC source code: See details of which class and which line at https://gist.github.com/739523
method(type argument)
{
  if(argument == null){
    throw new ArgumentNullException("argument")
  }


...
}
So, in total this pattern introduces 312 lines of duplicate code without whitespaces and 644 lines of duplicate code including whitespaces. And the pattern is simple, just check a condition and throw exception if its true. Not to mention, there are numerous other duplications where string.IsNullOrEmpty is used to check for string arguments.
This observation is interesting to me. Since, I think it adds a lot of noise to the code. In fact, if you randomly look at any of the methods - you have a good chance of seeing the first few lines doing this exactly similar thing. And this adds noise to me. Not to mention that, the developer needs to write the code, write tests for this code and if one needs to use this method, somehow should know this in advance that passing a null will result in an exception. But of course, this is not explicit from the method signature unless the developer also takes the pain to put a documentation styled comment and mention about this ArgumentNullException.
To remove this clutter, I think C# can introduce a few language keywords such as the follows:
public void Authenticate(required User user)
public void AddNewUser(nonblank string userName)
A compiler can very easily compile the code and put the exception throwing logic based on these keywords. Call it a syntactic sugar or a language keyword, this is the kind of translation that seems to be perfect for the compilers. And I can foresee it being used in almost all methods we write, since if the methods require an argument they do it for a purpose and most of the time null is not expected anyway!
I don't know if this will reach the people responsible for developing C#, but if it does, I think the community will really love this new language feature.
I know about workarounds using AOP or other hyped-but-seldom-used tricks to solve this problem. But these tricks often make life harder by introducing a learning curve and then punishing the learning by slowing down the application. So, its best to put in as a core language feature. What do you think?

Friday, December 10, 2010

Book Review: Jose Valim's Crafting Rails Applications

Have you already read this?

The following excerpt  by Jose Valim at the end of the book nicely summarizes it:
Finally, you understand Rails better. You can explore other areas of the source code, study other Action Controller and Active Models modules, check other generators implementations or read the source of Railties, Engines and Applications with detail! - Jose Valim
For the impatient readers, this is the best in-depth Ruby on Rails related book I have ever read and you should read this (only 172 pages). Buy the book here. But wait, you could get 40% discount and get the book for $13. I will tell you how, continue reading!
This book literally opens up the Ruby on Rails framework for the readers. So, now I am crystal clear about Metal, Rack, ActiveModel, Rendering, Templating, Migrations, Gems, Engines and so many core concepts. If you are like me, you have cloned the Ruby on Rails code and took a peek into the code to understand, patch some code or just to learn some hidden treasures of Ruby, but had tough time getting hold of the big picture. Well, this book will show you some highways and also some other useful alleys - you can find the rest by yourself!
This book embraces Test Driven Design, so all code examples, and hell yes there's a lot of them, are test driven. So, its unit test, functional test and integration test that drives the show. The topics cover customization of key Ruby on Rails components such as: models, controllers, views, mailers, generators and rack integrations. But the examples are really good as it shows:

  • Responding to pdf requests so that the server responds with on-the-fly PDF responses
  • Using Markdown templates for producing HTML and Text multipart emails from a single source template
  • Rendering views that are stored in a database to work as a simple CMS
  • Publishing and subscribing to Rails internal event such as SQL queries
  • Creating a simple rack application
  • Creating a Rails Engine
  • Creating custom responders so that you can DRY up your controllers that use exactly same lines for respond_to do |format|...
  • I18n translations using Redis key-value store and caching
  • Combining Sinatra with Rails in a single Rails app
To ease the process of trying out the DIY code, Jose Valim created an excellent gem called enginex. This gem gives you an incubator to try out the example code while building your own gem and using it from an embedded dummy application, writing tests and even browsing the app. The whole experience of trying out the code is awesome. Before this, I have never read a book that shipped with a gem just so that the readers could easily use the source code. Awesome idea and even better execution.
While explaining the inner workings of Ruby on Rails framework the book also discussed about a few useful gems:
  1. devise - authentication gem.
  2. enginex - produces incubator for gem development and makes it a breeze.
  3. capybara - drives integrations tests and also works with browsers through selenium etc.
  4. rdiscount - Discount is an implementation of John Gruber's Markdown markup language in C
  5. responders - DRY up your Ruby on Rails application with a number of handy responders.
  6. redis - an easy to use Key Value store.
  7. prawn - Ruby PDF library.
This book also shows a number of cool tricks. Its overall a fun read. I would say, the final version will be  more eye-soothing, but don't wait for that. Grab your ebook now and you will get the updates as they come!
I would like the book more if Jose Valim could reorganize some of the content. For an example, the text about Generators appear in different places. I think it would be easier to follow if it was in a separate chapter. The same applies for Engine.
I have another observation: the book is written for pro developers with substantial Ruby/Rails application. But I think the topics discussed here could also be equally useful to beginners. The later can be achieved by going a bit slow about some of the topics. Jose Valim, can you add little explanations at places for beginners?
The bottom line is, buy this book and read. To receive 40% discount, sign up at http://pragprog.com and refer to a friend and ask her to complete signup. You both get 40% discount. To claim, go to your account and you will find this as soon as your friend completes the signup.
Thank you!
--
This review is not sponsored and contains my opinion only.