Monday, March 15, 2010

Just Do It : Programming to the Nike Approach.

After reading a recommended book by a friend, I wanted to talk about the Nike's old marketing slogan, "Just Do It.", and it's relationship to my programming experiences. Nike's "Just Do It" slogan really helps me answer those 50/50 questions or "hmm, we could probably use this snippet of code in other places, but I am not sure if it should be reused" or "this might be a pretty good idea, but I am not sure if we have permission to do it." you have when you are programming. Do what you think is right. Basically, JUST DO IT! There have been so many times another programmer or myself have been stuck or afraid of making a business decision becomes of fears of the wrong outcome. The fact is "no one likes to make decisions" period, so presenting it to another person really just causes frustration. So just code it the way you think it needs to be done.

Now, I am not saying you should do this for ever decision but most of the decisions left up to a developer are minor in the eyes of the user. They want you to tell them how they should work and they will tell you what's missing, named wrong, or doesn't work. So I invite you to be bold like Nike and "Just Do It.".

Throw that extra icon or link in there.
Set the smart default you think you would use the most.
Constrain the user to a set of options to choose from to better focus the experience.

Once it's coded and demo-able, have another couple set of eyes look at it. They will tell you what works and doesn't work, but at least you create some discussion on your concern by showing. Showing is such a strong yet hard thing to accomplish in programming, because it's hard to finish something. By getting something to show you are very close if not finished with your task. People aren't dump, they will notice the changes you did and if they don't that means they don't care and your in the clear or you chose "what the user will naturally want" and it will work. Either way it's a silent win for you.

If you spend too much time deciding how something should be done vs. doing it, more and more requests will be added and you will get overwhelmed with tasks. Just code it and demo it to a group of people, whom will spend the next week ripping and tweaking the piece you created, until they figure out what they want. Where this kinda sucks cause you will have to go back and look at your code, you will find out what worked and didn't, be able to create some direction for your self by involving others in your concerns, and be more prepared for the next task for which you can transfer the tips you learned. It also allows you to focus more on code instead of managing politics.

In recap...Just Do It!

Simplicity vs. DRY code

I was in a pickle today over whether or not to consolidate code or keep it a little bit wet for simplicity sake. I consider simplicity sake, going to a view and not having to unlock the rubric's cube of "if" logic. If you are not familiar with wet and dry code, wet is where you repeat yourself over and over and dry is where you "Don't Repeat Yourself (DRY)". I went with "Simplicity". I decided to consolidate parts of the view, yet repeat myself a little. I found this to be safe because I felt like the views would grow and I didn't want it to end up with a crazy page that only the maker has the key to unlocking its craziness. Yeah, we have all seen some of those old pages that are a disaster to debug and I didn't want to start that trend. Also, I wanted the next person behind me to get in and out of the view as quickly as possible. It wasn't very much fun going through every view and updating the same piece of code...but it was simple.

Sunday, March 14, 2010

Small == Big

Have you ever tried to over architect something so that it fits all cases and solves world hunger?

I think we have all ran into this problem before and I think it's due to fear. We are afraid that the wierd, the one-off case comes along and we have to re-work our code that we spent so much time and thought into. Let's be honest no-one likes to go back and repeat something all over again, just because of one little feature/request. Sadly, no matter what you do, it will quickly become out-dated and need to be looked at again. On the flip side, the cool part is that you get solve the issue in a new way.

One thing that helps remind me not to over architect something is to start small. Solve your issue for one record. Example: "Add one user to the system". Solving for one record helps you identify the core pieces that make up the record.

Next, go back and tweak your code to do a group of records. Example: "Add a group of users to the system." Processing records in a group helps save the end user time.

And finally package your code, if you it's generic enough, to be used by other systems. Packaging helps the next developer who needs to solve a similar issue jump start there development efforts and gives them a feeling of "safety net" that someone else can help them if they get stuck.

Going back and touching your code sucks but it can be made more fun if you try to solve for the group of records and packaging. It will help you discover a new solution to your issue and keep you interested in your re-work.

Remeber:
1. One record
2. A group of records
3. Package it for the next developer

Indexed views, not using your indexes

I was working on an export where we were building a query in a string to be passed to a CLR through a stored proc to a small .NET assembly on the db server and ran into some issues with performance. Now, of course CF is slow at running queries...that's why we passed to it .NET to handle the execution, but I didn't think .NET would be slow. I couldn't figure out why my query was slow for the life of me. All the indexes were place, no extra joins were added and the query still took 20 minutes to run. After talking to a DB developer he told me that even though we indexed the sql "views" the indexes were not being used. I quickly freaked out wondering why SQL didn't use the indexes on the views like it uses the indexes on the tables. It should be assumed. Turns out the reason was that, "It is just one of those things". To fix the issue we added "with noexpand" to the joins to the indexed view and then query time went down to about 8 seconds. Ridiculous.

StructSort() does not sort your keys

Ran into an issue on Friday where I was trying to sort a struct numerically by it's keys. My struct looked something like this {"1"= query,"11"=query,"2"=query}. I first tried StructSort(struct) but it didn't work for me, it kept erroring on me. I wanted my keys to be sorted like this 1,2,11 but we all know CF automatically sorts your structs alphabetically.

So I tested structSort() with a different struct like this {"1"= "1","11"="11","2"="2"}. Bam! It worked. Hmm...something is fishy here. StructSort() works with simply values, but not complex values...but it should be just looking at the struct's keys. Anyways got around it by doing this listSort(structKeyList(struct))

Tell the join how to join.

I have been having a lot issues…with query execution plans lately (using CF and SQL). SQL has been choosing shitty plans thus making my query slow. If you have ever looked at execution plans, they are difficult read...unless you are a DB developer. I have had no idea wtf was going on with these plans…until now. Another developer sent this great link explaining what the joins are doing in the execution plan. You can then tell your joins in your query how to join.

Example:
select * from [user]
inner hash join enterprise_user on enterprise_user.user_id = [user].id

An execution plan does more than just join identification, such as indexes, but the join thingy is all I really cared about at the moment.

P.S. Only specify the “how to join” if you have to; if your query blows at running, let SQL try to calculate the best plan.

Use Case: Had a query in cfquery tags and it was choosing an execution plan with nested loop joins instead of the fast hash joins.