How to keep code layout visually 'attractive' when introducing error handling? - layout

When writing code, I find it important that my code looks well (apart from the fact that it has to work well). It is well described in the book Code Complete (p729): 'The visual and intellectual enjoyment of well-formatted code is a pleasure that few nonprogrammers can appreciate'.
The problem is, as soon as I got my code functionally working, and I start to introduce error handling (try-except clauses etc.) to make it robust, I find that this usually messes up my well-laid out code and turns it into something that is definitely not visually pleasing. The try-except statements and additional if's, make the code less readable and structured.
I wonder if this is because I misuse or overuse error handling, or is this unavoidable?
Any tips or tricks to keep it good-looking?

It is hard to give you a general answer for this, since there are a lot of different cases of error handling and so there are a lot of different approaches to deal with this problem. If you would post some real-world examples, you probably would get a lot of suggestions here on SO how to improve your code.
In general, adding error handling to existing functions makes them bigger, so refactoring them up into smaller methods is always a good idea. If you are looking for a more general approach, you should make yourself comfortable with Aspect-Oriented programming. That is an approach to keep out the code for so-called cross cutting concerns (like error handling) completely out of your business logic code.
EDIT: Just one simple trick:
I avoid writing error-checks like this:
int MyFunction()
{
if( ErrorCheck1Passes())
{
if( ErrorCheck2Passes())
{
if( ErrorCheck3Passes())
{
callSomeFunction(...);
}
else
return failureCode3;
}
else
return failureCode2;
}
else
return failureCode1;
return 0;
}
I prefer
int MyFunction()
{
if( !ErrorCheck1Passes())
return failureCode1;
if( !ErrorCheck2Passes())
return failureCode2;
if( !ErrorCheck3Passes())
return failureCode3;
callSomeFunction(...);
return 0;
}

I often wrap up chunks of code that require error handling into their own functions that will handle all possible exceptions internally, and so in a sense always succeed. The code that calls them looks cleaner, and if those functions are called more than once, then your code also becomes smaller.
This can make more sense if you are working more at the front end of an application, where from the user's point of view not every single possible exception needs to bubble up to their level. It's fine in the context of some classes for there to be a robust internal way of handling errors and moving on.
So for example, I might have functions like
SaveSettingsSafe();
// 'Safe' in the sense that all errors are handled internally before returning

You have rediscovered a major reason that Don Knuth invented literate programming: it is all too common for error handling to obscure the main algorithm. If you're lucky, you'll have some language constructs that offer you some flexibility. For example, exceptions may let you move the error handling elsewhere, or first-class functions may make it possible to move error handling around and reduce if-then-else checks to a function call.
If you're stuck in a language without these features, like C, you might want to look into a literate-programming tool. Literate-programming tools are preprocessors, but their whole mission is to help you make your code more readable. They have a small but rabid following, and you'll be able to find some guidance on the web and in published papers.

It all depends on how you do your programming. You can avoid a lot of these try-catch (or as you put it, try-except) statements if you just do proper input validation. Sure, it's a lot of work to cover most of the junk users tend to put into forms etc, but it will keep your data handling routines clean (or cleaner).

Related

if and when try/except statements are overkill

Sorry if this isn't the right place to ask this. I'm still learning a lot about good design. I was just wondering, say I process raw data through 20 functions. Is it idiotic or extremely slow to think of wrapping the contents of each function with a try/except statement, so if I ever run into issues I can see exactly where and why the data wasn't properly processed? Surely there's another more efficient way of facilitating the debugging process.
I've tried searching through articles for if and when to use try/except statements. But I think the experience of some of the guys on stack overflow will provide a much better answer :)
I can only give my personal opinion, but i think you shouldn't wrap your entire code inside "try/except" conditions. To me, theses are meant for specific cases, when manipulating streams, sending HTTP request, to ensure that we don't reach a part of the code that won't run (or adopt specific behaviour depending on the error).
The risk is to catch an error from another line of your program, but without knowing it (for example if you wrap an entire function).
It is important to cover your code, but without completely hide every error that you could encounter.
you probably already checked it but a little reminders of good practices :
Try / Except good practices
I hope that's will be helpful !
When exceptions are raised (and recorded somewhere) they have a stacktrace showing the calls that lead to the error. That should be enough to trace where the problem was.
If you catch an exception at the lowest level, how will the subsequent methods continue? They'll not get the returned values they were expecting. Better to let the exception propagate up the process to somewhere it makes sense to handle it. If you do manual checks you can raise specific exceptions with messages to help debug, eg:
def foo(bar):
if bar < 0:
raise ValueError(f"Can't foo a value less than 0, got {bar}")
# foo bar here

JSLint and the "Expected to see a statement and instead saw a block." error

I have picked up the habit of wrapping all of my case statements in curly brackets from programming in C because of this but JSLint is throwing a fit. It stops validating at that point.
My question is: Is this such a bad practice in JS? Do I not have to worry about the scope issue because JS has function scope (I understand how that would be the case, I just want a good reason not to be 'consistent' on this)?
(I know that different languages call for different practices, but i am trying to be as consisten as possible across languages to help protect my sanity.)
Good question.
The reason that JSLint complains about this is because it is actually contrary to the language specification for the switch/case statments:
http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
https://developer.mozilla.org/en/JavaScript/Reference/Statements/switch
The JavaScript compier will tolerate it, however JSLint is about ensuring your code adheres to a stricter and more correct subset of JavaScript. ("The Good Bits" as Douglas Crockford puts it!)
Moreover, the extra bracing is extra characters that you will have to transmit with the website. If you don't need them, why transmit them?
Referring to your above link, the same problem does not present itself in JavaScript. So, the following will work:
var x = 0;
switch(x){
case 0:
var y = 1;
alert(y);
}
See it at this JSFiddle: http://jsfiddle.net/LKWwB/
Finally, regarding your sanity, I would relinquish the tenuous grip you have on it. I did years ago and am much happier for it :-)

Working with a severely limited interpreted language

I'm coding in an embedded language called JS.
I want to be able to call three functions in any order. (ABC, ACB, BAC, BCA, CBA, CAB.)
The trick? The language doesn't have user-defined functions.
It does have a conditional and a looping construct.
I think I have three choices.
Duplicate a whole bunch of code.
Write a preprocessor (that would create all the duplicated code).
Do a loop with three iterations, using an array to control which functionality gets called on each pass of the loop.
I hate #1. Duplicated code is nasty. How do I change anything without screwing up?
I guess #2 is OK. At least I don't have duplicated code in the source. But my output code is what I'll be debugging, and I wonder if I want to diverge from it. On the plus side, I could add a bunch of sugar to the language.
I think my best bet is #3.
Any other ideas? There is no goto. No functions. No existing preprocessor.
Funny thing about #3 is that it's essentially the infamous for/switch nightmare.
Perhaps some kind of mutant state-machine, viz:
int CODEWORD=0x123;
while (CODEWORD)
{
switch(CODEWORD&15)
{
case 1:
/// case 1
break;
case 2:
/// case 2
break;
case 3:
//// case 3
break;
}
CODEWORD=CODEWORD>>4;
}
DRY, no preprocessor, no array. for/switch seems somewhat unavoidable.
You might be able to use the C preprocessor instead of writing your own. That would at least let you try it to see if it's a workable solution.
The technically best solution (assuming that you have access to the code or the developers) is to modify the JS language to do what you really need.
Failing that, the best solution depends on aspects of the problem that you haven't explained:
are the 'functions' recursive?
are there function parameters?
do you need (are you likely to need) other control structures not provided in JS?
does the function call order depend on runtime parameters?
are you skilled and confident enough to design and implement a preprocessor language that meets your current and projected requirements?
is implementing a preprocessor going to save you / coworkers time in the long run?
If the answers to 5. and enough of the others are "yes", then your option #2 is the right answer. Otherwise ... an ugly solution like your #1 or #3 might actually be a better idea.
EDIT: If you don't have source code access and the development team is not responsive to your needs, consider looking for an open-source alternative.

Writing easily modified code

What are some ways in which I can write code that is easily modified?
The one I have learned from experience is that I almost always need to write one to throw away. That way I have developed a sense of the domain knowledge and program structure required before coding the actual application.
The general guidelines are offcourse
High cohesion, low coupling
Dont repeat yourself
Recognize design patterns and implement them
Dont recognize design patterns where they are not existing or necassary
Use a coding standard, stick to it
Comment everyting that should be commented, when in doubt : comment
Use unit tests
Write comments and tests before implementation, that way you know exactly what you want to do
And when it goes wrong : refactor, refactor, refactor. With good tests you can be sure nothing breaks
And oh yeah:
read this : http://www.pragprog.com/the-pragmatic-programmer
Everything (i think) above and more is in it
I think your emphasis on modifiability is more important than readability. It is not hard to make something easy to read, but the real test of how well it is understood comes when someone else (or you) has to modify it in repsonse to changing requirements.
What I try to do is assume that modifications will be necessary, and if it is not really clear how to do them, leave explicit directions in the code for how to do them.
I assume that I may have to do some educating of the reader of the code to get him or her to know how to modify the code properly. This requires energy on my part, and it requires energy on the part of the person reading the code.
So while I admire the idea of literate programming, that can be easily read and understood, sometimes it is more like math, where the only way to do it is for the reader to buckle down, pay close attention, re-read it a few times, and make sure they understand.
Readability helps a lot: If you do something non-obvious, or you are taking a shortcut, comment. Comments are places where you can go back and refactor if you have time later. Use sensible names for everything, makes it easier to understand what is going on.
Continuous revision will let you move from that first draft to a better one without throwing away (too much) work. Any time you rewrite from scratch you may lose lessons learned. As you code, use refactoring tools to eliminate code representing areas of exploration that are no longer needed, and to make obvious things that were obscure. The first one reduces the amount that you need to maintain; the second reduces the effort per square foot. (Sqft makes about as much sense as lines of code, really.)
Modularize appropriately and enforce encapsulation and separation of logic between your modules. You don't want too many dependencies on any one part of the code or that part becomes inherently harder to understand.
Considering using tried and true methods over cutting edge ones. You give up some functionality for predictability.
Finally, if this is code that people will be using before and after modification, you need(ed) to have an appropriate API insulating your code from theirs. Having a strong API lets you change things behind the scenes without needing to alert all your consumers. I think there's a decent article on Coding Horror about this.
Hang Your Code Out to D.R.Y.
I learned this early when assigned the task of changing the appearance of a web-interface. The code was in C, which I hated, and was compiled to a CGI executable. And, worse, it was built on a library that was abandoned—no updates, no support, and too many man-hours put into its use to change it. On top of the framework was a disorderly web of code, consisting of various form and element builders, custom string implementations, and various other arcane things (for a non-C programmer to commit suicide with).
For each change I made there were several, sometimes many, exceptions to the output HTML. Each one of these exceptions required a small change or improvement in the form builder, thanks to the language there's no inheritance and therefore only functions and structs, and instead of putting the hours in the team instead wrote these exceptions frequently.
In my inexperience I was forced to change the output of each exception, rather than consolidate the changes in an improved form builder. But, trawling through 15,000 lines of code for several hours after ineffective changes would induce code-burn, and a fogginess that took a night's sleep to cure.
Always run your code through the DRY-er.
The easiest way to modify a code is NOT to write code. Write pseudo code not just for algo but how your code should be structured if you are unsure.
Designing while writing code never works...for me :-)
Here is my current experience: I'm working (Java) with a kind of database schema that might often change (fields added/removed, data types modified). My strategy is to parse this schema and to generate the code with apache velocity. The BaseClass generated is never modified by the programmer. Else, a MyClass extends BaseClass is created and the logical components of this class (e.g. toString() ! )are implemented using the 'getters' and the 'setters' of the super class.

How do you write code that is easily read by other people who have had no hand in writing any part of it?

How do you write code that is easily read by other people and who have had no hand in writing any part of it?
The best way to ensure that others can read your code is to make sure that it is clear and concise. Namely,
Use self documenting names for variables, functions, and classes.
Comment complex algorithms so that the reader doesn't have to spend to long figuring out what it does.
Ensure that tabbing and line breaks are constant throughout the code.
Beyond that you start to get in to the areas that might be a bit subjective, most people should agree on these items.
You may want to take a look at Clean Code by Robert C. Martin. It offers up a lot of useful practices for ensuring your code is readable.
Additionally, if your code is supported by a number of unit tests that thoroughly test your code, it offers a way for your user to understand the code by looking at what the tests are doing. You will also find that if you follow the Test Driven Development process, and you write tests for each bit of functionality, your functions tend to be small, do one thing only and do it well, and tend to flow more like a story than simply a large complex web of "stuff".
Tests tend to stay up-to-date more than comments. I often ignore comments anymore due to simple fact that they become obsolete very quickly.
This question is subjective, and should be avoided on StackOverflow, as per the FAQ
What kind of questions should I not
ask here?
Avoid asking questions that are
subjective, argumentative, or require
extended discussion. This is a place
for questions that can be answered!
The short answer would be:
Avoid excessive commenting:
// add one to the count:
i++;
Use good variable and method names:
int x = i + j;
int runSum = prevSum += newValue;
Use coding shorthand where available:
if (x == y)
{
z = a;
}
else
{
z = b;
}
z = (x == y) ? a : b;
Keep code nice, clear and simple. Don't comment what you're doing when it's obvious (for instance I know what a foreach or if does, I don't normally need an explanation).
Code tricks (such as auto properties) that make simple things take up fewer lines are good too.
Buy & read Code Complete 2. There's loads of stuff in there about writing easy to read / maintain code.
I don't think it's a subjective question, but it's too broad! It's not just about commenting and giving good variables names. It deals with how humans comprehends code. So your system must be implemented in a way that the reader can easily construct a mental model of its design in two way:
Top-down: assuming the user knows the system domain, he tends to make assumptions on how it would be implemented, so he'll scan the system packages and classes looking for entities he can identify. Giving good names to your classes and properly modularizing it would help very much.
Bottom-up: once the user reaches a portion of code he'll start navigation from there, building chunks of knowledge. If your system has low cohesion and lots of implicit dependencies the user will be lost.
Kent Beck adopts three principles: Communication, Simplicity and Flexibility. Of course, sometimes you'll have to trade simplicity for flexibility, and vice-versa.
This could go on and on. The answer to this question fits in a large book. As #rmbarnes suggested, buy and read Code Complete 2. I also suggest Implementation Patterns by Kent Beck - its highly related to your question.
Document the code as to why it does what it does.
Make sure that all variables functions etc. are named consistently and descriptively
Use white space to group logical portions of code together, so it flows while reading.
Place the functions/methods etc. in a logical order.
(this one is my personal preference) Make sure that code can easily be read on the screen without having to scroll horizontally (some people say vertically too, but this doesn't seem to bother me).
Since everyone else said pretty much what I'm thinking when I read this question, I'll just share two books related to this subject that you might be interested in reading. These books use open source code examples to explain how to read and write high quality code. In addition to Code Complete, I think they are valuable resources when you want to write good code in any language.
Code Reading: The Open Source Perspective
Code Quality: The Open Source Perspective
My rules:
Give everything a meaningful name, and call it what it is. Avoid using "x" and "y" for variables.
Don't abbreviate ANYTHING. I don't care how long the variable name is, don't abbreviate, even with comments. Interpretation of abbreviations is subjective. Does Cmp mean computer? Computer? Company? Compliment? Make it a strong rule, no exceptions, and its easy to follow.
Don't put multiple statements on the same line. Each line performs a single action.
Avoid Hungarian Notation like the plague. Or is it ntHungarian?
Use brackets even for single-line (if, for) substructures. Indentation differences are too easy to lose.
A lot of good answers here, I would like to add something from the perspective of an engineer who likes the big picture. I frequently found that getting a high level overview, in terms of class diagram or a package level overview (diagram/comments etc), heck if nothing exists a 10 line header comments in a file to help me a lot. We can use Doxygen/Javadocs to generate them, or spend 10-15 minutes to just jot down something in comments section.
They dont have to be 100% accurate, and I doubt the overall structure of classes/packages will change without a complete rewrite.
I personally found this kind of big picture overview very helpful and am sure there are others who feel the same.
Probably the most important point is to keep your syntax consistent. I would also have a look at the design guidelines for the language you are writing in.
I am most likely in the minority, but I don't mind whitespace. I LOVE WHITESPACE. Since the compiler takes it out and HD space being so cheap I like to have white space in my code.
For example I like:
int total = 10;
int sum = 0;
for (int i = 0; i < total; i++)
{
sum += i;
}
// Next coding statement is a space below the bracket
return sum;
I do not like:
int total = 10;int sum = 0;
for (int i = 0; i < total; i++)
{
sum += i;
}
return sum;
What I also put in Brackets even though technically they are not needed. The best example is the if statement. I find it greatly helps readability.
if(true)
// some action
if(true)
{
// Some action
}
The best code to me, is one that as simple as possible. With the least comments as possible, and most importantly works.
From being a developer with several years under the belt, this used to be a real question for me. I couldn't even say how many hours I passed thinking about this and trying different things in my code. The above answers are very nice too. I just want to add a thing or two.
We each have different things that make our reading different than the others. Something that you find easy to read, might really be hard for somebody else to read.
Cleanliness of your code is a very important aspect. Soon as it gets too cramped just forget about it.
Most important: You are you own teacher. No matter what style you follow, you will want to change a thing or two based on your experience. As months pass and you have to go back to your old for fixes or documentation, you will have the "I can't believe I wrote code that reads like that" effect. Take notes of what was bugging you with the code readability and make sure not to write like that again.

Resources