Home

[icon] Friends
View:Recent Entries.
View:Archive.
View:Friends.
View:User Info.
You're looking at the latest 5 entries.

Tags:, , , , , , ,
Subject:Remote Model Designs for Web Apps
Time:06:06 pm
I've been involved with writing back-ends and (limited) front-ends for multiple web-apps over the course of my career and one pattern that I observed at the last 3 of my 4 workplaces was that the application started as a single unit running on a webserver but the model sooner or later got ripped out and deployed in a separate layer over the network.

There were different reasons for the model to be broken out. In one case, our team was the provider of some data (ratings and reviews) and all the data management logic. It soon stopped making sense and being feasible to package our code and get it deployed on rapidly growing client base. So we started offering it as a webservice. In the second instance, we had a website to display our data as part of the end-user experience but soon realised that there was demand for the data itself via the b2b channel, so we again created a webservice. In the third case, it was driven by a need to scale up and modularise a pretty large and complex web application that we had, and the first step was to decouple the data management from the application UI.

wsloader was a product of this observation. Having done this thrice over, I wanted to make the process as painless as possible -- even have it as the starting point in fresh application development.

This blog post is essentially just to discuss whether the repetition of this pattern has been a coincidence with me or is it a recurring pattern in the larger development ecosystem.

If it is a larger pattern, does it make sense to recognise an end-to-end development pattern wherein some toolkits or frameworks establish and automate the conventions in providing data services and some other toolkits establish the convention in usage of these services to build the UI -- whether it be for direct end-user interaction via different platforms (web, mobile web, etc.) or for integration into other applications or systems.

How many web applications have you built where you have (or wish you had) stuck a UI on top of decoupled data services? Do you think that the thick-server pattern as promoted by frameworks like Django, Rails, etc. is inherently not scalable? If it were a project specification to have remote data services and a decoupled UI layer, what tools would you use to work on that project?
comments: 1 comment or Leave a comment Add to Memories Tell a Friend

Tags:, , , , , ,
Current Location:Bengaluru, India
Subject:Three!
Time:02:56 pm
Current Mood:[mood icon] happy
Stacy, my car!


She's done slightly over 20,000 kilometres in three years. The best purchase I've made till date in Bangalore. Given the right tyre pressures (33 psi), she's a joy to drive!

Thanks to [info]code_martial for this awesome photograph!
comments: Leave a comment Add to Memories Tell a Friend

Tags:, , ,
Subject:KISS
Time:12:31 pm
A 5 year old article from my old website, salvaged from the Internet Archive.


We all know that one must KISS. But how does one KISS? This article is all about a hypothesis that if you try to KISS, you can also KISS.

Alright, so your Tech Lead has handed you down a nice interface design and done whatever was necessary to explain the behaviour of the system through those interfaces. Now what are you waiting for, stupid? Code it up and deliver it yesterday... er... whatever! In any case, it is your responsibility now to put together something that works. You are the developer who writes the first cut of fresh software.

You are the target of a zillion curses doled out by maintenance engineers who have to clean up the mess after you're done. You're at the recieving end of one bug report after another that comes out of the QA department while you're working on the next iteration of development. Life sure sounds like it's hell.

Everyone has his own opinions about how to handle this situation and so have I developed a set of guidelines to keep myself out of such situations. Do these work? Apparently they do, which is why I took time out to put this whole thing together, but YMMV.

Be honest, be shameless

We all make errors in life and more so while programming a computer, which involves giving very precise instructions because computers haven't yet reached the stage where one can expect them to DWIM. One of the often made mistakes I have come across is trying to keep everything under wraps when it comes to handling errors.

Do not handle errors that you can not.

Trying to cover up error conditions when you don't have any idea of what to do can often be dangerous. Once I was trying to access a web application that required a login. I gave my username and password and it failed to authenticate. I spent about half an hour trying to figure out what my password was and then going to the database itself and resetting the password to something new. Still no luck. On scanning the authentication code, I found that the implementer caught any exception and returned authentication failure. The actual reason for failure was that there was no database connection!

In another project, we started seeing errors in the logs that said there was no column called "Infinity". That looked like a division by zero error and it is apparently quite dumb to let a division happen without checking for division by zero. In reality the divisor was never supposed to be zero so the check was unnecessary. The best that could done was to check and report an error but that machinery was already in place and it worked. Had the case been hushed up, say, by setting the result to zero, we would have had bad data and not have noticed it.

The whole idea is for a program to fail noisily when it has to. This makes it easy to detect the failure at the point of occurence where you have most context available to figure out its cause. You can then choose to eliminate the cause or plan out a strategy to handle that failure. When you are writing lower layers of a system, you should dutifully report errors and not hush them up. It is for the higher layers to decide what to do. It may be a simple, “Sorry, there seems to be some problem doing foo. Please try again later.” or something more sophisticated like giving suggestions on how or when to get things done right.

Note that you'd be lucky if you follow the above style and the libraries you use report errors by throwing exceptions. With return codes it is your responsibility to check the error code and report it, otherwise you'll be simply swallowing it (and throwing an unrelated error somewhere later).

Cut the crap

The goal of an implementation engineer is to write code that:

  • is largely free of defects
  • has defects that can be detected easily and quite early
  • has a simple logic for the benefit of maintenance engineers
  • is well structured to ease evolution and perfective maintenance

I will try to show how aiming to cut the crap and keeping the number of lines in your source code at a minimum can help you in reaching these goals.

Keep It Short, Stupid

Software Engineering statistics show that the number of defects per line of code is roughly constant across all programming languages. That is the reason why usage of higher level languages is advocated. So, if you try to reduce lines of code within the decided language of implementation, you reduce the incidence of bugs as well. Once you have written a unit, you rescan it to see if there is some flab you can shed. Rescanning for re-implementation is inherently more rigorous than scanning for correctnes, because at each step you would be double-checking to ensure you don't break the behaviour. To keep it largely free of defects, KISS.

If we again recall our Software Engineering lessons we'll know that the earlier a defect is found, the easier it is to rectify it. When less amount of code does more work, more things break if it is buggy, making things easier to detect. With more bug reports, you also get more context to examine and pin-point the defect. For code whose defects an be easily and quickly detected, KISS.

Trying to keep things short requires elimination of redundant code. This results in simplification of the underlying logic because someone reading your code has to deal with lesser number of confusing constructs likes loops and tests. Lesser amount of context needs to be kept in the head while going through it. It is also beneficial to do data transformation in less number of steps, each doing something significant, to keep things clear. To simplify your logic, KISS.

If done correctly, code elimination also leads to improvements in the internal design of code and makes things modular. For example, if you face several blocks of code, each with only minor variations, you factor out the common parts into one unit that the others depend on. This makes the unit that you have factored out more "responsible" and allows other blocks of code to off-load their responsibility to it. We all know the benefits of modular code, so I will just say that, to have well structured code, KISS.

Write disposable code

Now we move on to slightly more subjective issues. My suggestion is that when you write disposable code, you implicitly write maintainable and extensible code. What I mean by disposable code is your program is composed of a number of small, self-contained units such that any unit may be replaced with another unit that does the same job and it shouldn't required changes in other parts of the program. This is the holy grail of Component Based Software Engineering, and the general principle can be applied to micro level coding too.

When you try to make your code disposable, you end up writing modular, cohesive code that has a high degree of invariance. Modularity implies that your codebase is divided into neat sections, each having its own set of responsibilities. Cohesivity implies that related things appear together in your codebase. Invariance implies that changes in one part of your codebase do not require changes in other parts. Perfective maintenance and behavioural enhancements then become easier because you don't have to worry about introducing regression errors, unless the behavioural change itself is incompatible with the previous behaviour.

Now that I have harped about all the virtues of writing disposable code, what does it take to figure out that a maintainer would be too hesitant to dispose off pagefuls of code because he can't be sure of its repercussions? Joel Spolsky thinks that rewriting from scratch is a bad idea. Writing disposable code allows you to get a lot done without resorting to a rewrite from scratch.

Don't mind obfuscating in favour of saving loc numbers

Okay, that was just to wake you up. Writing obfuscated code is a crime against humanity. Often people get the wrong ideas about obfuscation, however. Being terse is not obfuscation. Even in activities other than programming, like public speech or daily conversation, verbosity is not appreciated. Why then do you think (if you do think that way) that being verbose in code is going to make things clear? To me, it is more clear if you write something like:

   return !call_a_function();

than something like:

   int retval = call_a_function();
   // If retval was zero we should return success (true)
   if (retval == 0)
   {
     return true;
   }
   // Otherwise we should return failure (false)
   else
   {
     return false;
   }

Another thing to remember is that once you are done coding the logic, you should do a second pass over what you have written. Usually when you are not implementing a well defined algorithm, you tend to evolve some logic as you code. Evolutionary coding of logic looks clear and simple to the implementer because it is a reification of his thought process. However, it isn't necessarily simple for someone who is reading through it for the first time and trying to decipher it. More often than not, such evolutionary code has redundant loops, conditionals and unnecessary explicit temporaries, that get in a reader's way of understanding the logic. Like Eric Raymond says in his book, “The Art of UNIX Programming”, Chapter 1, Section 9:

“You'll carelessly complicate when you should be relentlessly simplifying — and then you'll wonder why your code bloats and debugging is so hard.... You need to care. You need to play. You need to be willing to explore.”

After you are done with cutting the flab off your logic, you can get some more mileage if you know the style conventions of your programming language. Every language has a bunch of idiomatic way of doing things. Those idioms are very well recognised and their usage makes your code no less clear. The most illustrative example of idiomatic usage, perhaps, is the short-circuit behaviour of “logical and” and “logical or” operators. Use these style conventions and idioms as often as you can. Of course, a lot also depends on the syntax of your programming language .Some languages are more easy to obfuscate (Perl?) than others (Python!). Though business logic is usually so simple that you have to try hard to obfuscate its implementation, my personal observation is that the above, seemingly counter-intuitive tips work for algorithmic code as well.

When worse comes to worst, and you manage to obfuscate your code, be good and make it disposable. The maintenance engineer who has to deal with it (and that may very well be you), he can bug the local language expert for deciphering it out. He might also offer advice on how to rewrite it better, and teach you some other tricks. In the extreme worst case, your code might have to be thrown away, so it should be easily replaceable.

Tahir Hashmi 2005-01-07

comments: 2 comments or Leave a comment Add to Memories Tell a Friend

Time:08:05 am


Tweetup :: Tweetup on Improving Collective Intelligence (via @dhempe, @dorait, @santoshp) #twtvite

Posted using ShareThis
comments: Leave a comment Add to Memories Tell a Friend

Tags:,
Current Location:Delhi
Subject:p.r.i.o.r.i.t.i.e.s
Time:06:26 pm
Current Mood:[mood icon] contemplative
With the thesis coming to a close (well almost), I have a feeling that I will have no work left to do. Wonder how my days and years are going to be spent henceforth, and what my priorities in life are going to be. I wonder. One thing, which I can visualise is that research work and career will always be on top of my list and other things will take a backseat. If it is not this way, than I will be a very unhappy person. But if things happen the way I visualise, then again, how happy and contented will I be? I dont have a clue. Can we really change the course of our life ourselves? Maybe not.
comments: 3 comments or Leave a comment Add to Memories Tell a Friend

Advertisement

[icon] Friends
View:Recent Entries.
View:Archive.
View:Friends.
View:User Info.
You're looking at the latest 5 entries.