views:

165

answers:

12

I'm having a debate with some engineers and trying to decide on the right choice here. I'd like to get your thoughts on this topic. Totally subjective.

We've built an API for an iPhone app. It connects to our pre-existing business layer. The API is stateless but requires authentication for most calls/actions. But because there is authentication required, the API was originally designed to make a DB call first to get the User object, and then to extract our ID from that and use it to perform the requested action. So all in all - this design means a minimum of 2 DB calls for every action performed.

The alternative was to change the design so that each action didn't require 2 DB calls, but that the call would include the ID, username, pwd encrypted into one hash tag, which could then be decrypted on the server side API to remove the need to make another DB call just to get the ID for the requested action.

The argument is that with the extra code to encrypt/decrypt that it would be a costly choice to include this additional code and wasn't worth the extra time to change it just to reduce the DB calls by one.

This seems like a no brainer to me, but please enlighten me with your thoughts. My thought is that I'd rather take the hit internally in code maintenance costs, and not put that extra wait time on the users.

Again, totally subjective. Please forgive me for my ignorance. I'm a single engineer maintaining a lot of code on a high-volume site. Both speed and code maintenance costs are important to me.

Additional Info
Great responses everyone! Here are a few more details.

It's correct, it's not an extra round trip to from the iPhone to the server, but from the web server to the db server. 2 WebSvr-to-DB trips for any action performed on the iPhone vs 1 when using the encryption technique mentioned.

I have not measured or benchmarked anything, as part of the argument is about limited resources. Benchmarking it is certainly how I'd prefer to decide, but this will ultimately take twice or three times as long as just making the change. Maybe it's best to bite the bullet on it? Data driven decisions provide the most confidence.

Speed on the website, DB and iPhone are already an issue. So doing what we can to speed it up is something we are looking to accomplish. This greatly contributes to the decision and should have mentioned it initially.

About network latency + cost of the DB lookup. I can only speed up the DB call and not the latency unless we decide to do some type of caching. My thought is is that decrypting one string will always be faster than the latency of a round trip to the DB. I will do a quick test on this.

I'm still leaning toward my push to reduce the DB calls because it's seems vague to consider the cost of code maintenance in this case since the difference in code we're talking about it simply the code it takes to encrypt/decrypt a string. If performance is one of our concerns, choosing to add more load to the DB just makes optimization more of an urgent matter because we didn't make a conscious decision to reduce DB resources when we had a chance.

Besides my need to decide on this soon and move forward, I find this question extremely interesting and find myself in these kinds of debates more and more lately.

+6  A: 

It is be better to satisfy the customer (decrease load time) since they ultimately pay the bills.

xeon
+1  A: 

If you're being paid per hour, decrease the code maintenance costs. Else, go for the speed increase.

paulbeesley
I as sarcastic as the next a**Hole, but A post like this one is asking for a serious answer.
Jim C
I'm sorry? I was being perfectly serious. If the customer is paying per hour then results are important and code maintainability has a direct impact on that. If the project is billed as a single entity then perhaps performance takes priority.
paulbeesley
+2  A: 

Have you been able to measure the impact of the extra DB call in any way to ensure that it is actually a problem worth worrying about? A code or SQL profiler might be able to give you a bit more information to either reinforce your argument or show that it doesn't really matter compared to the other actions being taken.

  • Does it significantly impact server load?
  • Does it noticably affect the users experience?

There are also many ways to optimise data access, are these your only options?

Generic Error
A: 

Are you sure that replacing a DB call with something where you now need encryption will speed things up? This may be less of an issue on the server side (although you say it's high volume) and more of an issue on the client side. If this is in fact a win, then you may wish to consider locally (in the server) caching the user mapping to avoid having to do the DB lookups for each action.

Have you profiled and found that DB access is a significant enough issue that it's worth reducing the number of DB accesses? If not, you may want to profile your app first, to find out where the bottlenecks really are. If you profile and the DB lookups are indeed a significant fraction of each user action's time, then it sounds like it's worth doing the change you're talking about.

Eddie
A: 

From the sounds of it, the question could be re-phrased "reduce the DB calls by one" to "reduce the number of round trips from the iPhone to the server by half".

If so, the user experience could be significantly improved by reducing the number of round trips, depending on the kind of network (and associated latency) you see your users connecting over. If they're connecting over 2G, reducing the number of round trips could make the interface feel significantly "crisper".

Neal Maloney
Unless you have a very wide CDN, I think that reducing round trips will make ANY operation much crisper. Even a wired connection cannot exceed the speed of light. Round trip for a ping to stackoverflow is over 100ms. Doubling the latency would be quite noticeable.
Brian
A: 

It's better to run it on a single round-trip. Regarding code maintenance, it's subjective, other programmers would find making two DB calls inelegant(may even make them think it's a code maintenance) before they would have a thought of it being slow.

For your customer's sake, go for speed. Code is ephemeral, impression is forever.

Michael Buen
A: 

Realistically, how much time does it take to add the code - minutes? A few hours?

How often do you expect this app to be available in the wild - for the next few years?

Which makes more sense from that perspective, removing a redundant DB call that will be (hopefully) thousands of times in the next few years? Or saving four hours?

Not sure if I understand how this impacts code maintainability - why not just add this method to your API as an additional method side-by-side with the others?

matt b
A: 

I'd go for increased maintenability since lateley programmer brain hours are more scarce than computing power.

Also, if the performace hit is definetely too high, the increased maintenability allows for easier profiling and fix.

See this post on Coding Horror

Reginaldo
Ah, but the price he is paying is a networking price, not a hardware price. And latency, unlike bandwidth, cannot be improved beyond certain hard limits...unless you find a way to transmit information faster than the speed of light.
Brian
+4  A: 

It is a false dichotomy. Code maintenance is not inverse to load speed - with care, it is possible to make something both maintainable and which does not perform outrageously bad.

In practice, actually, it may even be easier to find bottlenecks and optimize code which is more maintainable than code which isn't.

thomasrutter
A: 

I suggest you see if you can port one of the many Session management modules used so frequently to deal with this specific problem.

le dorfier
A: 

The maintenance cost is obviously there - copy and pasting the same code into every single DB function, even if it's a single method call followed by a check, is a great way to introduce bugs and difficulty.

What is your exact setup though? There is the possiblity of packaging both commands into a single DB call without hardcoding the ID method into every single function.

It sounds like you have a set of stored procedures like this:
(excuse the extreme pseudo code)

getValidatedID(username, password) returns ID  
getUsersFoos(ID) returns Foos  
getUsersBars(ID) returns Bars

Normally you'd call these individually, for 2 round trips:

ID = ExecuteSQL("exec getValidatedID('...','...')")
Foos = ExecuteSQL("exec getUsersFoos(" + ID +")")

But does your database and calling model support something like this:

Foos = ExecuteSQL("DECLARE @ID; exec @ID = getValidatedID('...','...'); exec getUsersFoos(@ID)")
David
A: 

I would favor maintenance as long as the performance is acceptable.

Premature optimization is the devil you know. :)

Dana Holt