Assignment in method call bad practice? - c#

This is my first question to Stackoverflow, although I have been a consumer for many years. Please forgive me if I break rules. That is certainly not my intent. I have strenuously reviewed the rules and believe I am within the bounds of acceptability. However, I would ask that you kindly point out usage errors, if they are present, so that I may in future be more compliant.
I teach programming to high school students. This semester we are doing C#. Last week we were studying recursion. I assigned several classic problems that can be solved with recursion, one of them being exponentiation.
One of my students submitted the following code as a solution for exponentiation using recursion (he did give me permission to post it here). The assignment in the method call gave me the willies, but when I told him that it was bad practice, he protested, saying that "it works", that it "made sense" to him, and that he "does it all the time".
static void Recur(int n1, int n2, int n3)
{
if (n2 > 0)
{
Recur(n1, n2 - 1, n3 *= n1); // this is the line in question
}
else
{
Console.WriteLine("The number calculated recursively is: {0}", n3);
}
}
I have had a hard time coming up with something concrete to tell my student about why making an assignment in a method call is bad practice in general, other than 1) the possibility of unintended side effects, and 2) the difficulty of maintenance.
I have searched online with every phrase I can construct concerning this question, but have come up pretty empty-handed. I did see a reference to a book called "Clean Code" by Robert C. Martin that I don't own.
My relationship with my students is somewhat like that of a parent. They sometimes don't put a lot of stock in what I say unless I can corroborate it with an independent source. If I could point to a definitive statement about putting assignments in a method call my student would be more inclined to stop this annoying habit.
Does this usage bother anyone else? Am I expecting too much in wanting him to change the way he's been doing things? He's 15, but with a promising future ahead of him. He's one of those students who just "gets it". I don't want him to develop bad practices.
Thank you for your time and input.

There are quite a few things improvable in the posted code:
Be consistent
Why isn't the call Recur(n1, n2 =- 1, n3 *= n1)? Why is n3 treated differently? This can cause confusion when reviewing/mantaining code.
Dont do unnecessary or superfluous work
Is n3 ever used after Recur(n1, n2 - 1, n3 *= n1)? No? Then why waste time assigning a value that is never used?
It's considered good practice to not mutate method arguments (unless they are passed in by reference of course). Why? Because it makes debugging and understanding how the code works much harder; having the initial conditions mutate as the method executes makes it much harder to track possible bugs, optimizations, improvements, etc.
All that said, I avoid these kind of patterns because I have really bad memory:
var i = 0;
Foo(i += 1);
Bar(i);
What is passed into Foo? Was it 0 or was it 1? I never remember and I have to look it up everytime. Chances are that whoever reviews this code can have the same problem. These clever tricks don't make the code work any faster or better and it avoids a grand total of one code line... not worth it.

The bad code is this one: n3 *= n1
Your student doesn't see any problem because method parameters are not final. Just define them final and you will see this peace of code will cause a compile error.
Why should one use final? Because this makes sure the method parameters will not be used for any other purposes inside the method. This makes the code less error prone, more reliable. Using one variably for one purpose makes also the code easier to understand by others which is important in the industry.
And as already pointed by others, assigning a value to n3 makes not sense because further on variable n3 is not used in the code.
His statement that this "makes sense to him" shows that he does not about software development in the real life, in the industry - starting from small companies and to Google or Facebook. One of the requirements is that the code should be maintainable. This peace of code is not.
Regarding "with a promising future ahead of him": How do you know that? Did he win any programming competition? His argument that he "does it all the time" is pretty weak. Ask him why does he do it? Give him a small research about the code quality. May be this will help him to understand software development a little bit.

Related

Does inverting the "if" improve performance? [duplicate]

When I ran ReSharper on my code, for example:
if (some condition)
{
Some code...
}
ReSharper gave me the above warning (Invert "if" statement to reduce nesting), and suggested the following correction:
if (!some condition) return;
Some code...
I would like to understand why that's better. I always thought that using "return" in the middle of a method problematic, somewhat like "goto".
It is not only aesthetic, but it also reduces the maximum nesting level inside the method. This is generally regarded as a plus because it makes methods easier to understand (and indeed, many static analysis tools provide a measure of this as one of the indicators of code quality).
On the other hand, it also makes your method have multiple exit points, something that another group of people believes is a no-no.
Personally, I agree with ReSharper and the first group (in a language that has exceptions I find it silly to discuss "multiple exit points"; almost anything can throw, so there are numerous potential exit points in all methods).
Regarding performance: both versions should be equivalent (if not at the IL level, then certainly after the jitter is through with the code) in every language. Theoretically this depends on the compiler, but practically any widely used compiler of today is capable of handling much more advanced cases of code optimization than this.
A return in the middle of the method is not necessarily bad. It might be better to return immediately if it makes the intent of the code clearer. For example:
double getPayAmount() {
double result;
if (_isDead) result = deadAmount();
else {
if (_isSeparated) result = separatedAmount();
else {
if (_isRetired) result = retiredAmount();
else result = normalPayAmount();
};
}
return result;
};
In this case, if _isDead is true, we can immediately get out of the method. It might be better to structure it this way instead:
double getPayAmount() {
if (_isDead) return deadAmount();
if (_isSeparated) return separatedAmount();
if (_isRetired) return retiredAmount();
return normalPayAmount();
};
I've picked this code from the refactoring catalog. This specific refactoring is called: Replace Nested Conditional with Guard Clauses.
This is a bit of a religious argument, but I agree with ReSharper that you should prefer less nesting. I believe that this outweighs the negatives of having multiple return paths from a function.
The key reason for having less nesting is to improve code readability and maintainability. Remember that many other developers will need to read your code in the future, and code with less indentation is generally much easier to read.
Preconditions are a great example of where it is okay to return early at the start of the function. Why should the readability of the rest of the function be affected by the presence of a precondition check?
As for the negatives about returning multiple times from a method - debuggers are pretty powerful now, and it's very easy to find out exactly where and when a particular function is returning.
Having multiple returns in a function is not going to affect the maintainance programmer's job.
Poor code readability will.
As others have mentioned, there shouldn't be a performance hit, but there are other considerations. Aside from those valid concerns, this also can open you up to gotchas in some circumstances. Suppose you were dealing with a double instead:
public void myfunction(double exampleParam){
if(exampleParam > 0){
//Body will *not* be executed if Double.IsNan(exampleParam)
}
}
Contrast that with the seemingly equivalent inversion:
public void myfunction(double exampleParam){
if(exampleParam <= 0)
return;
//Body *will* be executed if Double.IsNan(exampleParam)
}
So in certain circumstances what appears to be a a correctly inverted if might not be.
The idea of only returning at the end of a function came back from the days before languages had support for exceptions. It enabled programs to rely on being able to put clean-up code at the end of a method, and then being sure it would be called and some other programmer wouldn't hide a return in the method that caused the cleanup code to be skipped. Skipped cleanup code could result in a memory or resource leak.
However, in a language that supports exceptions, it provides no such guarantees. In a language that supports exceptions, the execution of any statement or expression can cause a control flow that causes the method to end. This means clean-up must be done through using the finally or using keywords.
Anyway, I'm saying I think a lot of people quote the 'only return at the end of a method' guideline without understanding why it was ever a good thing to do, and that reducing nesting to improve readability is probably a better aim.
I'd like to add that there is name for those inverted if's - Guard Clause. I use it whenever I can.
I hate reading code where there is if at the beginning, two screens of code and no else. Just invert if and return. That way nobody will waste time scrolling.
http://c2.com/cgi/wiki?GuardClause
It doesn't only affect aesthetics, but it also prevents code nesting.
It can actually function as a precondition to ensure that your data is valid as well.
This is of course subjective, but I think it strongly improves on two points:
It is now immediately obvious that your function has nothing left to do if condition holds.
It keeps the nesting level down. Nesting hurts readability more than you'd think.
Multiple return points were a problem in C (and to a lesser extent C++) because they forced you to duplicate clean-up code before each of the return points. With garbage collection, the try | finally construct and using blocks, there's really no reason why you should be afraid of them.
Ultimately it comes down to what you and your colleagues find easier to read.
Guard clauses or pre-conditions (as you can probably see) check to see if a certain condition is met and then breaks the flow of the program. They're great for places where you're really only interested in one outcome of an if statement. So rather than say:
if (something) {
// a lot of indented code
}
You reverse the condition and break if that reversed condition is fulfilled
if (!something) return false; // or another value to show your other code the function did not execute
// all the code from before, save a lot of tabs
return is nowhere near as dirty as goto. It allows you to pass a value to show the rest of your code that the function couldn't run.
You'll see the best examples of where this can be applied in nested conditions:
if (something) {
do-something();
if (something-else) {
do-another-thing();
} else {
do-something-else();
}
}
vs:
if (!something) return;
do-something();
if (!something-else) return do-something-else();
do-another-thing();
You'll find few people arguing the first is cleaner but of course, it's completely subjective. Some programmers like to know what conditions something is operating under by indentation, while I'd much rather keep method flow linear.
I won't suggest for one moment that precons will change your life or get you laid but you might find your code just that little bit easier to read.
Performance-wise, there will be no noticeable difference between the two approaches.
But coding is about more than performance. Clarity and maintainability are also very important. And, in cases like this where it doesn't affect performance, it is the only thing that matters.
There are competing schools of thought as to which approach is preferable.
One view is the one others have mentioned: the second approach reduces the nesting level, which improves code clarity. This is natural in an imperative style: when you have nothing left to do, you might as well return early.
Another view, from the perspective of a more functional style, is that a method should have only one exit point. Everything in a functional language is an expression. So if statements must always have an else clauses. Otherwise the if expression wouldn't always have a value. So in the functional style, the first approach is more natural.
There are several good points made here, but multiple return points can be unreadable as well, if the method is very lengthy. That being said, if you're going to use multiple return points just make sure that your method is short, otherwise the readability bonus of multiple return points may be lost.
Performance is in two parts. You have performance when the software is in production, but you also want to have performance while developing and debugging. The last thing a developer wants is to "wait" for something trivial. In the end, compiling this with optimization enabled will result in similar code. So it's good to know these little tricks that pay off in both scenarios.
The case in the question is clear, ReSharper is correct. Rather than nesting if statements, and creating new scope in code, you're setting a clear rule at the start of your method. It increases readability, it will be easier to maintain, and it reduces the amount of rules one has to sift through to find where they want to go.
Personally I prefer only 1 exit point. It's easy to accomplish if you keep your methods short and to the point, and it provides a predictable pattern for the next person who works on your code.
eg.
bool PerformDefaultOperation()
{
bool succeeded = false;
DataStructure defaultParameters;
if ((defaultParameters = this.GetApplicationDefaults()) != null)
{
succeeded = this.DoSomething(defaultParameters);
}
return succeeded;
}
This is also very useful if you just want to check the values of certain local variables within a function before it exits. All you need to do is place a breakpoint on the final return and you are guaranteed to hit it (unless an exception is thrown).
Avoiding multiple exit points can lead to performance gains. I am not sure about C# but in C++ the Named Return Value Optimization (Copy Elision, ISO C++ '03 12.8/15) depends on having a single exit point. This optimization avoids copy constructing your return value (in your specific example it doesn't matter). This could lead to considerable gains in performance in tight loops, as you are saving a constructor and a destructor each time the function is invoked.
But for 99% of the cases saving the additional constructor and destructor calls is not worth the loss of readability nested if blocks introduce (as others have pointed out).
Many good reasons about how the code looks like. But what about results?
Let's take a look to some C# code and its IL compiled form:
using System;
public class Test {
public static void Main(string[] args) {
if (args.Length == 0) return;
if ((args.Length+2)/3 == 5) return;
Console.WriteLine("hey!!!");
}
}
This simple snippet can be compiled. You can open the generated .exe file with ildasm and check what is the result. I won't post all the assembler thing but I'll describe the results.
The generated IL code does the following:
If the first condition is false, jumps to the code where the second is.
If it's true jumps to the last instruction. (Note: the last instruction is a return).
In the second condition the same happens after the result is calculated. Compare and: got to the Console.WriteLine if false or to the end if this is true.
Print the message and return.
So it seems that the code will jump to the end. What if we do a normal if with nested code?
using System;
public class Test {
public static void Main(string[] args) {
if (args.Length != 0 && (args.Length+2)/3 != 5)
{
Console.WriteLine("hey!!!");
}
}
}
The results are quite similar in IL instructions. The difference is that before there were two jumps per condition: if false go to next piece of code, if true go to the end. And now the IL code flows better and has 3 jumps (the compiler optimized this a bit):
First jump: when Length is 0 to a part where the code jumps again (Third jump) to the end.
Second: in the middle of the second condition to avoid one instruction.
Third: if the second condition is false, jump to the end.
Anyway, the program counter will always jump.
In theory, inverting if could lead to better performance if it increases branch prediction hit rate. In practice, I think it is very hard to know exactly how branch prediction will behave, especially after compiling, so I would not do it in my day-to-day development, except if I am writing assembly code.
More on branch prediction here.
That is simply controversial. There is no "agreement among programmers" on the question of early return. It's always subjective, as far as I know.
It's possible to make a performance argument, since it's better to have conditions that are written so they are most often true; it can also be argued that it is clearer. It does, on the other hand, create nested tests.
I don't think you will get a conclusive answer to this question.
There are a lot of insightful answers there already, but still, I would to direct to a slightly different situation: Instead of precondition, that should be put on top of a function indeed, think of a step-by-step initialization, where you have to check for each step to succeed and then continue with the next. In this case, you cannot check everything at the top.
I found my code really unreadable when writing an ASIO host application with Steinberg's ASIOSDK, as I followed the nesting paradigm. It went like eight levels deep, and I cannot see a design flaw there, as mentioned by Andrew Bullock above. Of course, I could have packed some inner code to another function, and then nested the remaining levels there to make it more readable, but this seems rather random to me.
By replacing nesting with guard clauses, I even discovered a misconception of mine regarding a portion of cleanup-code that should have occurred much earlier within the function instead of at the end. With nested branches, I would never have seen that, you could even say they led to my misconception.
So this might be another situation where inverted ifs can contribute to a clearer code.
It's a matter of opinion.
My normal approach would be to avoid single line ifs, and returns in the middle of a method.
You wouldn't want lines like it suggests everywhere in your method but there is something to be said for checking a bunch of assumptions at the top of your method, and only doing your actual work if they all pass.
In my opinion early return is fine if you are just returning void (or some useless return code you're never gonna check) and it might improve readability because you avoid nesting and at the same time you make explicit that your function is done.
If you are actually returning a returnValue - nesting is usually a better way to go cause you return your returnValue just in one place (at the end - duh), and it might make your code more maintainable in a whole lot of cases.
I'm not sure, but I think, that R# tries to avoid far jumps. When You have IF-ELSE, compiler does something like this:
Condition false -> far jump to false_condition_label
true_condition_label:
instruction1
...
instruction_n
false_condition_label:
instruction1
...
instruction_n
end block
If condition is true there is no jump and no rollout L1 cache, but jump to false_condition_label can be very far and processor must rollout his own cache. Synchronising cache is expensive. R# tries replace far jumps into short jumps and in this case there is bigger probability, that all instructions are already in cache.
I think it depends on what you prefer, as mentioned, theres no general agreement afaik.
To reduce annoyment, you may reduce this kind of warning to "Hint"
My idea is that the return "in the middle of a function" shouldn't be so "subjective".
The reason is quite simple, take this code:
function do_something( data ){
if (!is_valid_data( data ))
return false;
do_something_that_take_an_hour( data );
istance = new object_with_very_painful_constructor( data );
if ( istance is not valid ) {
error_message( );
return ;
}
connect_to_database ( );
get_some_other_data( );
return;
}
Maybe the first "return" it's not SO intuitive, but that's really saving.
There are too many "ideas" about clean codes, that simply need more practise to lose their "subjective" bad ideas.
There are several advantages to this sort of coding but for me the big win is, if you can return quick you can improve the speed of your application. IE I know that because of Precondition X that I can return quickly with an error. This gets rid of the error cases first and reduces the complexity of your code. In a lot of cases because the cpu pipeline can be now be cleaner it can stop pipeline crashes or switches. Secondly if you are in a loop, breaking or returning out quickly can save you a lots of cpu. Some programmers use loop invariants to do this sort of quick exit but in this you can broke your cpu pipeline and even create memory seek problem and mean the the cpu needs to load from outside cache. But basically I think you should do what you intended, that is end the loop or function not create a complex code path just to implement some abstract notion of correct code. If the only tool you have is a hammer then everything looks like a nail.

Do you like languages that let you put the "then" before the "if"?

I was reading through some C# code of mine today and found this line:
if (ProgenyList.ItemContainerGenerator.Status != System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) return;
Notice that you can tell without scrolling that it's an "if" statement that works with ItemContainerGenerator.Status, but you can't easily tell that if the "if" clause evaluates to "true" the method will return at that point.
Realistically I should have moved the "return" statement to a line by itself, but it got me thinking about languages that allow the "then" part of the statement first. If C# permitted it, the line could look like this:
return if (ProgenyList.ItemContainerGenerator.Status != System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated);
This might be a bit "argumentative", but I'm wondering what people think about this kind of construct. It might serve to make lines like the one above more readable, but it also might be disastrous. Imagine this code:
return 3 if (x > y);
Logically we can only return if x > y, because there's no "else", but part of me looks at that and thinks, "are we still returning if x <= y? If so, what are we returning?"
What do you think of the "then before the if" construct? Does it exist in your language of choice? Do you use it often? Would C# benefit from it?
Let's reformat that a bit and see:
using System.Windows.Controls.Primitives;
...
if (ProgenyList.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
{
return;
}
Now how hard is it to see the return statement? Admittedly in SO you still need to scroll over to see the whole of the condition, but in an IDE you wouldn't have to... partly due to not trying to put the condition and the result on the same line, and party due to the using directive.
The benefit of the existing C# syntax is that the textual order reflects the execution order - if you want to know what will happen, you read the code from top to bottom.
Personally I'm not a fan of "return if..." - I'd rather reformat code for readability than change the ordering.
I don't like the ambiguity this invites. Consider the following code:
doSomething(x)
if (x > y);
doSomethingElse(y);
What is it doing? Yes, the compiler could figure it out, but it would look pretty confusing for a programmer.
Yes.
It reads better. Ruby has this as part of its syntax - the term being 'statement modifiers'
irb(main):001:0> puts "Yay Ruby!" if 2 == 2
Yay Ruby!
=> nil
irb(main):002:0> puts "Yay Ruby!" if 2 == 3
=> nil
To close, I need to stress that you need to 'use this with discretion'. The ruby idiom is to use this for one-liners. It can be abused - however I guess this falls into the realm of responsible development - don't constrain the better developers by building in restrictions to protect the poor ones.
It's look ugly for me. The existing syntax much better.
if (x > y) return 3;
I think it's probably OK if the scope were limited to just return statements. As I said in my comment, imagine if this were allowed:
{
doSomething();
doSomethingElse();
// 50 lines...
lastThink();
} if (a < b);
But even just allowing it only on return statements is probably a slippery slope. People will ask, "return x if (a); is allowed, so why not something like doSomething() if (a);?" and then you're on your way down the slope :)
I know other languages do get away with it, but C#'s philosophy is more about making The One Right WayTM easy and having more than one way to do something is usually avoided (though with exceptions). Personally, I think it works pretty well, because I can look at someone else's code and know that it's pretty much in the same style that I'd write it in.
I don't see any problem with
return 3 if (x > y);
It probably bothers you because you are not accustomed to the syntax. It is also nice to be able to say
return 3 unless y <= x
This is a nice syntax option, but I don't think that c# needs it.
I think Larry Wall was very smart when he put this feature into Perl. The idea is that you want to put the most important part at the beginning where it's easy to see. If you have a short statement (i.e. not a compound statement), you can put it before the if/while/etc. If you have a long (i.e. compound) statement, it goes in braces after the condition.
Personally I like languages that let me choose.
That said, if you refactor as well as reformat, it probably doesn't matter what style you use, because they will be equally readable:
using System.Windows.Controls.Primitives;
...
var isContainersGenerated =
ProgenyList.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated;
if (!isContainersGenerated) return;
//alternatively
return if (!isContainersGenerated);
There is a concern reading the code that you think a statement will execute only later to find out it might execute.
For example if you read "doSomething(x)", you're thinking "okay so this calls doSomething(x)" but then you read the "if" after it and have to realise that the previous call is conditional on the if statement.
When the "if" is first you know immediately that the following code might happen and can treat it as such.
We tend to read sequentially, so reading and going in your mind "the following might happen" is a lot easier than reading and then realising everything you just read needs to be reparsed and that you need to evaluate everything to see if it's within the scope of your new if statement.
Both Perl and Ruby have this and it works fine. Personally I'm fine with as much functionality you want to throw at me. The more choices I have to write my code the better the overall quality, right? "The right tool for the job" and all that.
Realistically though, it's kind of a moot point since it's pretty late for such a fundamental addition in C#'s lifecycle. We're at the point where any minor syntax change would take a lot of work to implement due to the size of the compiler code and its syntax parsing algorithm. For a new addition to be even considered it would have to bring quite a bit of functionality, and this is just a (not so) different way of saying the same thing.
Humans read beginning to end. In analyzing code flow, limits of the short term memory make it more difficult to read postfix conditions due to additional backtracking required. For short expressions, this may not be a problem, but for longer expressions it will incur significant overhead for users that are not seasoned in the language they are reading.
Agreed with confusing , I never heard about this construction before , so I think correct way using then before if must always contents the result of else, like
return (x > y) ? 3 : null;
else way there is no point of using Imperative constructions like
return 3 if (x > y);
return 4 if (x = y);
return 5 if (x < y);
imho It's kinda weird, because I have no idea where to use it...
It's like a lot of things really, it makes perfect sense when you use it in a limited context(a one liner), and makes absolutely no sense if you use it anywhere else.
The problem with that of course is that it'd be almost impossible to restrict the use to where it makes sense, and allowing its use where it doesn't make sense is just odd.
I know that there's a movement coming out of scripting languages to try and minimize the number of lines of code, but when you're talking about a compiled language, readability is really the key and as much as it might offend your sense of style, the 4 line model is clearer than the reversed if.
I think it's a useful construct and a programmer would use it to emphasize what is important in the code and to de-emphasize what is not important. It is about writing intention-revealing code.
I use something like this (in coffeescript):
index = bla.find 'a'
return if index is -1
The most important thing in this code is to get out (return) if nothing is found - notice the words I just used to explain the intention were in the same order as that in the code.
So this construct helps me to code in a way which reflects my intention slightly better.
It shouldn't be too surprising to realize that the order in which correct English or traditional programming-language grammar has typically required, isn't always the most effective or simplest way to create meaning.
Sometimes you need to let everything hang out and truly reassess what is really the best way to do something.
It's considered grammatically incorrect to put the answer before the question, why would it be any different in code?

.net code readability and maintainability [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
There Currently is a local debate as to which code is more readability
We have one programmer who comes from a c background and when that programmer codes it looks like
string foo = "bar";
if (foo[foo.Length - 1] == 'r')
{
}
We have another programmer that doesn't like this methodology and would rather use
if (foo.EndsWith("r"))
{
}
which way of doing these types of operations is better?
EndsWidth is more readable to someone who has never seen C or C++, C#, or any other programming language.
The second one is more declarative in style but I can't tell you objectively if it is more readable sine readability is very subjective. I personally find the second one more readable myself but that is just my opinion.
Here is an excerpt from my article:
Most C# developers are very familiar
with writing imperative code (even
though they may not know it by that
name). In this article, I will
introduce you to an alternative style
of programming called declarative
programming. Proper declarative code
is easier to read, understand, and
maintain.
As professionals, we should be
striving to write better code each
day. If you cannot look at code you
wrote three months ago with a critical
eye and notice things that could be
better, then you have not improved and
are not challenging yourself. I
challenge you to write code that is
easier to read and understand by using
declarative code.
Number 2 is better to read and to mantain.
Example: Verify the last 2 characters ...
Option 1)
if (foo[foo.Length - 1] == 'r' && foo[foo.Length - 2] == 'a')
{
}
Option 2)
if (foo.EndsWith("ar"))
{
}
last 3? last 4?...
I come from a C/C++ background and I vote for Endswith!
Readability rules, especially if it implies intent.
With the first example I must discover the intent - which is left for interpretation. If it appears to have a bug, how do I know that's not intentional?
The second example is telling me the intent. We want to find the end character. Armed with that knowledge I can proceed with evaluating the implementation.
I think the second way is better because it is more easy to read and because the first one duplicates logic of EndsWith method which is bad practice.
I think the right answer would be the one that is actually correct. EndsWith properly returns false for empty string input whereas the other test will throw an exception trying to index with -1.
Not only is EndWith more readable, but also more 'correct'.
As a rule, if there is a framework method provided to do the job ... use it.
What if foo == string.Empty?
IMO, the intent of the original author is clearer in the second example. In the first, the reader must evaluate what the author is trying to accomplish by pulling the last index. It is not difficult, but requires more effort on the part of the reader.
Both approaches are valid, but the endswith method is easier to read in my opinion. It also does away with the potential to make typing mistakes etc with the more complicated form..
EndsWith is probably safer. But the indexer is probably faster.
Endswith probably checks to see if the input string is empty. They will probably both throw null reference exceptions. And the indexer will fail is the length is 0.
As for readability, they both say the same thing to me, but I have been programming for a while. The .EndsWith(...) is probably faster to grasp without considering context.
It pretty much does the same thing. However, it gets more complicated with more than one character in the endswith argument. However, the first example is slightly faster as it uses no actual functions and thus requires no stack. You might want to define a macro which can be used to simply make everything uniform.
I think the main criteria should be which of these most clearly says what the developer wants to do. What does each sample actually say?
1)Access the character at position one less than the length, and check if it equals the character 'r'
2)Check if it ends with the string "r"
I think that makes it clear which is the more maintainable answer.
Unless and until it does not affect the program performance, no problem you can use either way. But adding code comments is very important for conveying what is being accomplished.
From an error handling standpoint, EndsWith.
I much prefer the second (EndsWith) version. It's clear enough for even my manager to understand!
The best practice is to write code that is easily readable. If you used the first one, developers that are debugging your code may say, "What is this dev trying to do?" You need to utilize methods that are easily explained. If a method is too complicated to figure out, retract several methods out of it.
I would definitely say the second one, legibility and simplicity are key!
Also, if the "if" statement has one line, DONT BOTHER USING BRACES, USE A SINGLE INDENTION
Remember that in classic C, the only difference between a "string" and an array of characters is that terminating null character '\0', so we had to more actively treat them accordingly and to make sure that we did not run off the end of the array. So the first block of code bases its thought process on the concept of an array of characters.
The second block of code bases the thought process on how you handle a string more abstractly and with less regard to its implementation under the covers.
So in a nutshell, if you are talking about processing characters as the main idea behind your project, go with the first piece. If you are talking about preparing a string for something greater and that does not necessarily need to focus on the mechanics of the ways that strings are built -- or you just want to keep it simple -- go with the second style.
Some of this might summarize others' contributions at this point, but more analogously put, are you playing "Bingo();" or are you "playing a game with a two-dimensional array of random integers, etc.?"
Hopefully this helps.
Jim
"Code is written to be read by humans and incidently run by computers" SICP
EndsWith FTW!!

Invert "if" statement to reduce nesting

When I ran ReSharper on my code, for example:
if (some condition)
{
Some code...
}
ReSharper gave me the above warning (Invert "if" statement to reduce nesting), and suggested the following correction:
if (!some condition) return;
Some code...
I would like to understand why that's better. I always thought that using "return" in the middle of a method problematic, somewhat like "goto".
It is not only aesthetic, but it also reduces the maximum nesting level inside the method. This is generally regarded as a plus because it makes methods easier to understand (and indeed, many static analysis tools provide a measure of this as one of the indicators of code quality).
On the other hand, it also makes your method have multiple exit points, something that another group of people believes is a no-no.
Personally, I agree with ReSharper and the first group (in a language that has exceptions I find it silly to discuss "multiple exit points"; almost anything can throw, so there are numerous potential exit points in all methods).
Regarding performance: both versions should be equivalent (if not at the IL level, then certainly after the jitter is through with the code) in every language. Theoretically this depends on the compiler, but practically any widely used compiler of today is capable of handling much more advanced cases of code optimization than this.
A return in the middle of the method is not necessarily bad. It might be better to return immediately if it makes the intent of the code clearer. For example:
double getPayAmount() {
double result;
if (_isDead) result = deadAmount();
else {
if (_isSeparated) result = separatedAmount();
else {
if (_isRetired) result = retiredAmount();
else result = normalPayAmount();
};
}
return result;
};
In this case, if _isDead is true, we can immediately get out of the method. It might be better to structure it this way instead:
double getPayAmount() {
if (_isDead) return deadAmount();
if (_isSeparated) return separatedAmount();
if (_isRetired) return retiredAmount();
return normalPayAmount();
};
I've picked this code from the refactoring catalog. This specific refactoring is called: Replace Nested Conditional with Guard Clauses.
This is a bit of a religious argument, but I agree with ReSharper that you should prefer less nesting. I believe that this outweighs the negatives of having multiple return paths from a function.
The key reason for having less nesting is to improve code readability and maintainability. Remember that many other developers will need to read your code in the future, and code with less indentation is generally much easier to read.
Preconditions are a great example of where it is okay to return early at the start of the function. Why should the readability of the rest of the function be affected by the presence of a precondition check?
As for the negatives about returning multiple times from a method - debuggers are pretty powerful now, and it's very easy to find out exactly where and when a particular function is returning.
Having multiple returns in a function is not going to affect the maintainance programmer's job.
Poor code readability will.
As others have mentioned, there shouldn't be a performance hit, but there are other considerations. Aside from those valid concerns, this also can open you up to gotchas in some circumstances. Suppose you were dealing with a double instead:
public void myfunction(double exampleParam){
if(exampleParam > 0){
//Body will *not* be executed if Double.IsNan(exampleParam)
}
}
Contrast that with the seemingly equivalent inversion:
public void myfunction(double exampleParam){
if(exampleParam <= 0)
return;
//Body *will* be executed if Double.IsNan(exampleParam)
}
So in certain circumstances what appears to be a a correctly inverted if might not be.
The idea of only returning at the end of a function came back from the days before languages had support for exceptions. It enabled programs to rely on being able to put clean-up code at the end of a method, and then being sure it would be called and some other programmer wouldn't hide a return in the method that caused the cleanup code to be skipped. Skipped cleanup code could result in a memory or resource leak.
However, in a language that supports exceptions, it provides no such guarantees. In a language that supports exceptions, the execution of any statement or expression can cause a control flow that causes the method to end. This means clean-up must be done through using the finally or using keywords.
Anyway, I'm saying I think a lot of people quote the 'only return at the end of a method' guideline without understanding why it was ever a good thing to do, and that reducing nesting to improve readability is probably a better aim.
I'd like to add that there is name for those inverted if's - Guard Clause. I use it whenever I can.
I hate reading code where there is if at the beginning, two screens of code and no else. Just invert if and return. That way nobody will waste time scrolling.
http://c2.com/cgi/wiki?GuardClause
It doesn't only affect aesthetics, but it also prevents code nesting.
It can actually function as a precondition to ensure that your data is valid as well.
This is of course subjective, but I think it strongly improves on two points:
It is now immediately obvious that your function has nothing left to do if condition holds.
It keeps the nesting level down. Nesting hurts readability more than you'd think.
Multiple return points were a problem in C (and to a lesser extent C++) because they forced you to duplicate clean-up code before each of the return points. With garbage collection, the try | finally construct and using blocks, there's really no reason why you should be afraid of them.
Ultimately it comes down to what you and your colleagues find easier to read.
Guard clauses or pre-conditions (as you can probably see) check to see if a certain condition is met and then breaks the flow of the program. They're great for places where you're really only interested in one outcome of an if statement. So rather than say:
if (something) {
// a lot of indented code
}
You reverse the condition and break if that reversed condition is fulfilled
if (!something) return false; // or another value to show your other code the function did not execute
// all the code from before, save a lot of tabs
return is nowhere near as dirty as goto. It allows you to pass a value to show the rest of your code that the function couldn't run.
You'll see the best examples of where this can be applied in nested conditions:
if (something) {
do-something();
if (something-else) {
do-another-thing();
} else {
do-something-else();
}
}
vs:
if (!something) return;
do-something();
if (!something-else) return do-something-else();
do-another-thing();
You'll find few people arguing the first is cleaner but of course, it's completely subjective. Some programmers like to know what conditions something is operating under by indentation, while I'd much rather keep method flow linear.
I won't suggest for one moment that precons will change your life or get you laid but you might find your code just that little bit easier to read.
Performance-wise, there will be no noticeable difference between the two approaches.
But coding is about more than performance. Clarity and maintainability are also very important. And, in cases like this where it doesn't affect performance, it is the only thing that matters.
There are competing schools of thought as to which approach is preferable.
One view is the one others have mentioned: the second approach reduces the nesting level, which improves code clarity. This is natural in an imperative style: when you have nothing left to do, you might as well return early.
Another view, from the perspective of a more functional style, is that a method should have only one exit point. Everything in a functional language is an expression. So if statements must always have an else clauses. Otherwise the if expression wouldn't always have a value. So in the functional style, the first approach is more natural.
There are several good points made here, but multiple return points can be unreadable as well, if the method is very lengthy. That being said, if you're going to use multiple return points just make sure that your method is short, otherwise the readability bonus of multiple return points may be lost.
Performance is in two parts. You have performance when the software is in production, but you also want to have performance while developing and debugging. The last thing a developer wants is to "wait" for something trivial. In the end, compiling this with optimization enabled will result in similar code. So it's good to know these little tricks that pay off in both scenarios.
The case in the question is clear, ReSharper is correct. Rather than nesting if statements, and creating new scope in code, you're setting a clear rule at the start of your method. It increases readability, it will be easier to maintain, and it reduces the amount of rules one has to sift through to find where they want to go.
Personally I prefer only 1 exit point. It's easy to accomplish if you keep your methods short and to the point, and it provides a predictable pattern for the next person who works on your code.
eg.
bool PerformDefaultOperation()
{
bool succeeded = false;
DataStructure defaultParameters;
if ((defaultParameters = this.GetApplicationDefaults()) != null)
{
succeeded = this.DoSomething(defaultParameters);
}
return succeeded;
}
This is also very useful if you just want to check the values of certain local variables within a function before it exits. All you need to do is place a breakpoint on the final return and you are guaranteed to hit it (unless an exception is thrown).
Avoiding multiple exit points can lead to performance gains. I am not sure about C# but in C++ the Named Return Value Optimization (Copy Elision, ISO C++ '03 12.8/15) depends on having a single exit point. This optimization avoids copy constructing your return value (in your specific example it doesn't matter). This could lead to considerable gains in performance in tight loops, as you are saving a constructor and a destructor each time the function is invoked.
But for 99% of the cases saving the additional constructor and destructor calls is not worth the loss of readability nested if blocks introduce (as others have pointed out).
Many good reasons about how the code looks like. But what about results?
Let's take a look to some C# code and its IL compiled form:
using System;
public class Test {
public static void Main(string[] args) {
if (args.Length == 0) return;
if ((args.Length+2)/3 == 5) return;
Console.WriteLine("hey!!!");
}
}
This simple snippet can be compiled. You can open the generated .exe file with ildasm and check what is the result. I won't post all the assembler thing but I'll describe the results.
The generated IL code does the following:
If the first condition is false, jumps to the code where the second is.
If it's true jumps to the last instruction. (Note: the last instruction is a return).
In the second condition the same happens after the result is calculated. Compare and: got to the Console.WriteLine if false or to the end if this is true.
Print the message and return.
So it seems that the code will jump to the end. What if we do a normal if with nested code?
using System;
public class Test {
public static void Main(string[] args) {
if (args.Length != 0 && (args.Length+2)/3 != 5)
{
Console.WriteLine("hey!!!");
}
}
}
The results are quite similar in IL instructions. The difference is that before there were two jumps per condition: if false go to next piece of code, if true go to the end. And now the IL code flows better and has 3 jumps (the compiler optimized this a bit):
First jump: when Length is 0 to a part where the code jumps again (Third jump) to the end.
Second: in the middle of the second condition to avoid one instruction.
Third: if the second condition is false, jump to the end.
Anyway, the program counter will always jump.
In theory, inverting if could lead to better performance if it increases branch prediction hit rate. In practice, I think it is very hard to know exactly how branch prediction will behave, especially after compiling, so I would not do it in my day-to-day development, except if I am writing assembly code.
More on branch prediction here.
That is simply controversial. There is no "agreement among programmers" on the question of early return. It's always subjective, as far as I know.
It's possible to make a performance argument, since it's better to have conditions that are written so they are most often true; it can also be argued that it is clearer. It does, on the other hand, create nested tests.
I don't think you will get a conclusive answer to this question.
There are a lot of insightful answers there already, but still, I would to direct to a slightly different situation: Instead of precondition, that should be put on top of a function indeed, think of a step-by-step initialization, where you have to check for each step to succeed and then continue with the next. In this case, you cannot check everything at the top.
I found my code really unreadable when writing an ASIO host application with Steinberg's ASIOSDK, as I followed the nesting paradigm. It went like eight levels deep, and I cannot see a design flaw there, as mentioned by Andrew Bullock above. Of course, I could have packed some inner code to another function, and then nested the remaining levels there to make it more readable, but this seems rather random to me.
By replacing nesting with guard clauses, I even discovered a misconception of mine regarding a portion of cleanup-code that should have occurred much earlier within the function instead of at the end. With nested branches, I would never have seen that, you could even say they led to my misconception.
So this might be another situation where inverted ifs can contribute to a clearer code.
It's a matter of opinion.
My normal approach would be to avoid single line ifs, and returns in the middle of a method.
You wouldn't want lines like it suggests everywhere in your method but there is something to be said for checking a bunch of assumptions at the top of your method, and only doing your actual work if they all pass.
In my opinion early return is fine if you are just returning void (or some useless return code you're never gonna check) and it might improve readability because you avoid nesting and at the same time you make explicit that your function is done.
If you are actually returning a returnValue - nesting is usually a better way to go cause you return your returnValue just in one place (at the end - duh), and it might make your code more maintainable in a whole lot of cases.
I'm not sure, but I think, that R# tries to avoid far jumps. When You have IF-ELSE, compiler does something like this:
Condition false -> far jump to false_condition_label
true_condition_label:
instruction1
...
instruction_n
false_condition_label:
instruction1
...
instruction_n
end block
If condition is true there is no jump and no rollout L1 cache, but jump to false_condition_label can be very far and processor must rollout his own cache. Synchronising cache is expensive. R# tries replace far jumps into short jumps and in this case there is bigger probability, that all instructions are already in cache.
I think it depends on what you prefer, as mentioned, theres no general agreement afaik.
To reduce annoyment, you may reduce this kind of warning to "Hint"
My idea is that the return "in the middle of a function" shouldn't be so "subjective".
The reason is quite simple, take this code:
function do_something( data ){
if (!is_valid_data( data ))
return false;
do_something_that_take_an_hour( data );
istance = new object_with_very_painful_constructor( data );
if ( istance is not valid ) {
error_message( );
return ;
}
connect_to_database ( );
get_some_other_data( );
return;
}
Maybe the first "return" it's not SO intuitive, but that's really saving.
There are too many "ideas" about clean codes, that simply need more practise to lose their "subjective" bad ideas.
There are several advantages to this sort of coding but for me the big win is, if you can return quick you can improve the speed of your application. IE I know that because of Precondition X that I can return quickly with an error. This gets rid of the error cases first and reduces the complexity of your code. In a lot of cases because the cpu pipeline can be now be cleaner it can stop pipeline crashes or switches. Secondly if you are in a loop, breaking or returning out quickly can save you a lots of cpu. Some programmers use loop invariants to do this sort of quick exit but in this you can broke your cpu pipeline and even create memory seek problem and mean the the cpu needs to load from outside cache. But basically I think you should do what you intended, that is end the loop or function not create a complex code path just to implement some abstract notion of correct code. If the only tool you have is a hammer then everything looks like a nail.

Are these interview questions too challenging for beginners? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
So I just interviewed two people today, and gave them "tests" to see what their skills were like. Both are entry level applicants, one of which is actually still in college. Neither applicant saw anything wrong with the following code.
I do, obviously or I wouldn't have picked those examples. Do you think these questions are too harsh for newbie programmers?
I guess I should also note neither of them had much experience with C#... but I don't think the issues with these are language dependent.
//For the following functions, evaluate the code for quality and discuss. E.g.
//E.g. could it be done more efficiently? could it cause bugs?
public void Question1()
{
int active = 0;
CheckBox chkactive = (CheckBox)item.FindControl("chkactive");
if (chkactive.Checked == true)
{
active = 1;
}
dmxdevice.Active = Convert.ToBoolean(active);
}
public void Question2(bool IsPostBack)
{
if (!IsPostBack)
{
BindlistviewNotification();
}
if (lsvnotificationList.Items.Count == 0)
{
BindlistviewNotification();
}
}
//Question 3
protected void lsvnotificationList_ItemUpdating(object sender, ListViewUpdateEventArgs e)
{
ListViewDataItem item = lsvnotificationList.Items[e.ItemIndex];
string Email = ((TextBox)item.FindControl("txtEmailAddress")).Text;
int id = Convert.ToInt32(((HiddenField)item.FindControl("hfID")).Value);
ESLinq.ESLinqDataContext db = new ESLinq.ESLinqDataContext();
var compare = from N in db.NotificationLists
where N.ID == id
select N;
if (compare.Count() > 0)
{
lblmessage.Text = "Record Already Exists";
}
else
{
ESLinq.NotificationList Notice = db.NotificationLists.Where(N => N.ID == id).Single();
Notice.EmailAddress = Email;
db.SubmitChanges();
}
lsvnotificationList.EditIndex = -1;
BindlistviewNotification();
}
I don't typically throw code at someone interviewing for a position and say "what's wrong?", mainly because I'm not convinced it really finds me the best candidate. Interviews are sometimes stressful and a bit overwhelming and coders aren't always on their A-game.
Regarding the questions, honestly I think that if I didn't know C#, I'd have a hard time with question 3. Question #2 is a bit funky too. Yes, I get what you're going for there but what if the idea was that BindlistviewNotification() was supposed to be called twice? It isn't clear and one could argue there isn't enough info. Question 1 is easy enough to clean up, but I'm not convinced even it proves anything for an entry-level developer without a background in C#.
I think I'd rather have something talk me through how they'd attack a problem (in pseudo-code or whatever language they are comfortable with) and assess them from that. Just a personal opinion, though.
I am a junior programmer, so I can give it a try:
"active" is unnecessary:
CheckBox chkactive = (CheckBox)item.FindControl("chkactive");
dmxdevice.Active = chkactive.Checked
You should use safe casting to cast to a CheckBox object. Of course, you should be able to find the checkbox through its variable name anyway.:
CheckBox chkactive = item.FindControl("chkactive") as CheckBox;
The second function could be more concise:
public void Question2(bool IsPostBack)
{
if (!IsPostBack || lsvnotificationList.Items.Count == 0)
{
BindlistviewNotification();
}
}
Only have time for those two, work is calling!
EDIT: I just realized that I didn't answer your question. I don't think this is complicated at all. I am no expert by any means and I can easily see the inefficiencies here. I do however think that this is the wrong approach in general. These language specific tests are not very useful in my opinion. Try to get a feeling for how they would attack and solve a problem. Anyone who can get past that test will be able to easily pick up a language and learn from their mistakes.
I think you are testing the wrong thing. You are obviously looking for a C# programmer, rather than a talented programmer (not that you cannot be a talented C# programmer). The guys might be great C++ programmers, for example. C# can be learned, smarts cannot. I prefer to ask for code during an interview, rather than presenting code in a specific language (example: implement an ArrayList and a LinkedList in any language).
When I was looking for 3 programmers earlier this year, to work mostly in C#, Java, PL/SQL, Javascript and Delphi, I looked for C/C++ programmers, and have not been disappointed. Any one can learn Java, not everyone has a sense of good arachitecture, data strutures and a grasp of new complex problems. C++ is hard, so it acts as a good filter. If I had asked find errors in this Java code, I would have lost them.
BTW, I am a team lead, been programming for 20 years with dozens of large projects developed on time and on budget, and I had no clue with what was wrong with question 2 or 3, having only a passing familiarity with C#, and certainly not with Linq, Not that I could not learn it.... I figured it out after a couple minutes, but would not expect a recent graduate to grasp it, all the LINQ code in question 3 is a distraction that hides the real problems.
Do you think these questions are too harsh for newbie programmers?
Yes, IMO they are too harsh.
Neither applicant saw anything wrong with the following code.
While there are plenty of 'possible problems', like not checking for null pointers, casting, etc, there don't appear to be any 'actual problems.' (eg: given sane input, the program looks like it will actually run).
I'd guess that a newbie programmer will get hung up on that.
As linq is pretty new, and still not in wide use, it's going to go way over the head of your newbies.
What is an ESLinqDataContext? If people have no idea what your object is or how it behaves, how are they supposed to know if it is being used correctly or not?
evaluate the code for quality and discuss
You only really learn to pick up stuff like invalid cast exceptions (let alone being able to judge and comment on 'code quality') from reasonable experience working with code similar to what's in front of you.
Perhaps I'm misunderstanding, but to me, an "entry level" position pretty much by definition has no expectation of prior experience, so it doesn't seem fair to grade them on criteria which require experience.
I am not a C# programmer so I don't know what BindlistviewNotification does, but changing
public void Question2(bool IsPostBack)
{
if (!IsPostBack)
{
foo();
}
if (lsvnotificationList.Items.Count == 0)
{
foo();
}
}
to
public void Question2(bool IsPostBack)
{
if (!IsPostBack || lsvnotificationList.Items.Count == 0)
{
foo();
}
}
changes the function! If IsPostBack is false, foo is executed. If lsvnotificationList.Items.Count == 0 then foo is executed again. The revised code will only execute foo once.
You could argue that BindlistviewNotification can be executed several times without side effects or that IsPostBack can never be false and lsvnotificationList.Items.Count equal 0 at the same time, but those are language dependent and implementation dependent issues that cannot be resolved with the given code snippet.
Also, if this is a bug that's "supposed" to be caught in the interview, this isn't language agnostic at all. There's nothing that would tell me that this is supposed to be a bug.
As a newbie, I would expect employers to care more about what my thought processes were rather than whether the answer was "correct" or not. I could come up with some answers to these questions, but they probably wouldn't be right. :)
So with that said, I think you could get by with these questions, but you should definitely be a bit more liberal with what the "correct" answer is.
As long as those conditions were made clear, I think that it's a bad thing to get a blank sheet with no thoughts. This means that they either genuinely think the code is perfect (which we know is almost never true) or are too sheepish to share their thoughts (which is also a bad thing).
I don't think 1 and 2 are too difficult, #3 requires a decent understanding on how databinding and LINQ works in .NET, so it may be somewhat hard for an entry level person. I think these are fairly good questions for junior level developers who have some .NET experience.
For what its worth, my notes:
Question 1:
Using an integer as boolean
No null check on findControl
Excessive verbosity
My revision:
public void Question1()
{
CheckBox chkactive = item.FindControl("chkactive") as CheckBox;
if (chkActive != null)
dmxdevice.Active = chkActive.Checked;
else
dmxdevice.Active = false;
}
Question 2:
Excessive verbosity
Databinding will happen twice if its not a postback, and there are no items to bind.
My revision:
public void Question2(bool IsPostBack)
{
if (!IsPostBack || lsnotificationList.Items.Count == 0)
{
BindlistviewNotification();
}
}
Question 3:
Replace indexed loopup with getting e.Item.DataItem;
Add nullchecks to findControl calls.
Switch to TryParse and add a default id value.
Added better error handling
Document some major architectural issues, why are you querying the database from the frontend? Those LINQ queries could be optimized too.
Why not check for duplicates within the list items collection, and why not batch all updates with a single submit later?
So you asked this to someone with no c#, .net, asp.net or linq knowledge? I wouldn't expected anything on the paper?
My only advice is to make sure your test questions actually compile.
I think the value in FizzBuzz type questions is watching HOW somebody solves your problems.
Watching them load the solution in to the IDE, compile it, step through the code with a step through debugger, write tests for the apparent intended behavior and then refactoring the code such that it is more correct/maintainable is more valuable than knowing that they can read code and comprehend it.
Not knowing C#, it took me a bit longer, but I'm assuming #1 could be expressed as
dmxdevice.Active = ((CheckBox)item.FindControl("chkactive")).Checked == true
And in #2 the two conditions could be joined as an A OR B statement?
If that's what you're looking for, then no, those aren't too hard. I think #1 is something you might learn only after programming for a little while, but #2 seems easier.
Are you looking for them to catch null pointer exceptions also?
I think the first two are fine. The third may be a wee bit complicated for a graduate level interview, but maybe not, it depends whether they've done any .net coding before.
It has LINQ statements in there, and that's pretty new. Especially since many unis/colleges are a bit behind in teaching the latest technology. So I would say run with 1 & 2 and either simplify 3 or heavily comment it as others have mentioned
The first two appear to be more a test to see if a person can follow logically and realize that there is extra code. I'm not convinced that an entry level developer would understand that 'less is more' yet. However, if you explained the answer to Question 1 and they did not then extraplolate that answer to #2, I would be worried.
Question 3 appears to be a big ball of mud type of implementation. This is almost expected to be the style of a junior developer straight from college. I remember most of my profs/TAs in college never read my code -- they only ran the executable and then put in test sets. I would not expect a new developer to understand what was wrong with it...
What did you expect to get out of this interview? Do your employees have to debug code without a debugger or something? Are you hiring somebody who will be doing only maintenance programming?
In my opinion these questions do little to enlighten you as to the abilities of the candidates.
This is a fine question if you're looking for a maintenance programmer, or tester.
However, this isn't a good test to detect a good programmer. A good programmer will pass this test, certainly, but many programmers that are not good will also pass it.
If you want a good programmer, you need to define a test that only a good programmer would pass. A good programmer has excellent problem solving skills, and knows how to ask questions to get to the kernel of a problem before they start working - saving both them and you time.
A good programmer can program in many different languages with only a little learning curve, so your 'code' test can consist of pseudo code. Tell them you want them to solve a problem and have them write the solution in pseudo code - which means they don't have access to all those nifty libraries. A good programmer knows how the libraries function and can re-create them if needed.
So... yeah, you're essentially asking textbook knowledge questions - items that show memorization and language knowledge, but not skills necessary to solve a problem.
-Adam
It's funny to see everyone jumping to change or fix the code. The questions targeted "efficiently? could it cause bugs?" Answers: Given enough time and money, sure each one could probably be made more efficient. Bugs, please try to avoid casting and writing difficult to read code (code should be self-documenting). If it doesn't have bugs it might after the next junior programmer tries to change it... Also, avoid writing code that appears to rely on state contained outside the scope of the method/function, those nasty global variables. If I got some insightful comments like this it might be appropriate to use this as a tool to create some good conversation. But, I think some better ice-breakers exist to determine if a persons critical thinking skills are appropriate and if they will fit in with the rest of the team. I don't think playing stump the programmer is very effective.
Question #1
boolean active = true;
Question #2
if ((!IsPostBack) || (lsvnotificationList.Items.Count == 0))
Question #3:
Do a total re-write and add comments. After a 30 second read I still can't tell what the code is trying todo.
I'm not a C# programmer. On Q1, there seem to be undeclared objects dmxdevice and item, which confuses me. However, there does seem to be a lot of obfuscation in the rest of the code. On Q2, lsvnotificationList is not declared, and it not clear to me why one test is abbreviated with ! and the other with == 0 -- but the tests could be combined with ||, it seems. In Q3, lsvnotificationList is not self-evidently declared, again. For the rest, it seems to be doing a database lookup using LINQ. I'd at least expect that to be factored into a function that validates the hidden field ID more transparently. But if you have other ideas, well...I'm still not a C# programmer.
Disclaimer: I come from a 4 year degree and a year's worth of professional Java experience.
The first two questions are quite straightforward and if a candidate doesn't see a better approach I would suspect it's because they haven't been paying attention in class ;-)
Most of the answers to the second question presented so far alter the functions behaviour. The function could very well be evaluated twice in the original code, although I can't say if that is the intent of the function. Side effects are important.
I would probably one-line the first function, myself.
The questions are fairly language agnostic, but they're not library agnostic, which I would argue is equally as important. If you're specifically looking for .NET knowledge, well and good, but without Google I couldn't tell you what an ESLinq.DataContext is, and my answer to the third question suffers accordingly. As it is, it's nearly incomprehensible to me.
I think you also have to be careful how you present the questions. There's nothing incorrect about the first two methods, per se. They're just a little more verbose than they should be.
I would just present them with the sheet and say, "What do you think of this code?"
Make it open ended, that way if they want to bring up error-handling/logging/commenting or other things, it doesn't limit the discussion.
A cursory glance indicates that most of the rest of the code suffers from poor structure and unnecessary conditionals etc. There's nothing inherently "wrong" with that, especially if the program runs as expected. Maybe you should change the question?
On the other hand, the casting doesn't look like it's being done correctly at all eg. (cast)object.Method() vs (cast)(object.Method()) vs ((cast)object).Method(). In the first case, it's not a language agnostic problem though - it depends on rules of precedence.
I don't think it was that hard, but it all depends on what you wanted to test. IMO, the smart candidate should have asked a lot of questions about the function of the program and the structure of the classes before attempting to answer. eg. How are they supposed to know if "item" is a global/member var if they don't ask? How do they know it's type? Do they even know if it supports a FindControl method? What about FindControl's return type?
I'm not sure how many colleges teach Linq yet though, so maybe you should remove that part.
No one's answering #3 with code. That should indicate how people feel about it. Usually stackoverflowers meet these head-first.
Here's my stab at it. I had to look up the EventArgs on msdn to know the properties. I know LINQ because I've studied it closely for the past 8 months. I don't have much UI experience, so I can't tell if the call to bind in the event handler is bad (or other such things that would be obvious to a UI coder).
protected void lsvnotificationList_ItemUpdating(object sender, ListViewUpdateEventArgs e)
{
string Email = e.NewValues["EmailAddress"].ToString();
int id = Convert.ToInt32(e.NewValues["ID"]);
using (ESLinq.ESLinqDataContext db = new ESLinq.ESLinqDataContext(connectionString))
{
List<NotificationList> compare = db.NotificationLists.Where(n => n.ID = id).ToList();
if (!compare.Any())
{
lblmessage.Text = "Record Does Not Exist";
}
else
{
NotificationList Notice = compare.First();
Notice.EmailAddress = Email;
db.SubmitChanges();
}
}
lsvnotificationList.EditIndex = -1;
BindlistviewNotification();
}
While people here obviously have no trouble hitting this code in their spare time, as someone who went through the whole job search/interviewing process fresh out of collage about a year ago I think you have to remember how stressful questions like these can be. I understand you were just looking for thought process, but I think you would get more out of people if you brought questions like this up casually and conversationally after you calm the interviewee down. This may sound like a cop out, but questions about code that will technically work, but needs some pruning, can be much more difficult then correcting code that doesn't compile, because people will assume that the examples are suppose to not compile, and will drive themselves up a wall trying to figure out the trick to your questions. Some people never get stressed by interview questions, but alot do, even some talented programmers that you probably don't want to rule out, unless you are preparing them for a situation where they have to program with a loaded gun to their head.
The code itself in question 3 seems very C# specific. I only know that as LINQ because someone pointed it out in the answers here, but coming in as a Java developer, I would not recognize that at all. I mean do you really expect colleges to teach a feature that was only recently introduced in .net 3.5?
I'd also liked to point out how many people here were tripped up by question 2, by streamlining the code, they accidentally changed the behavior of the code. That should tell you alot about the difficulty of your questions.
Ok, so after staying up well past my bedtime to read all the answers and comment on most of them...
General concensus seems to be that the questions aren't too bad but, especially for Q3, could be better served by using pseudo-code or some other technique to hide some of the language specific stuff.
I guess for now I'll just not weigh these questions in too heavily.
(Of course, their lack of SQL knowledge is still disturbing... if only because they both had SQL on their resume. :( )
I'll have to say that my answer to these problems is that without comments (or documentation) explaining what the code is MEANT to do, there is little reason to even look at the code. The code does EXACTLY what it does. If you change it to do something else, even change it to prevent throwing an exception, you may make it do something unintended and break the larger program.
The problem with all three questions is that there is no intent. If you modify the code, you are assuming that you know the intent of the original coder. And that assumption will often be wrong.
And to answer the question: Yes, this is too difficult for most junior programmers, because documenting code is never taught.
Okey I'm not going to answer the C# questions from what I see here you have enough candidates that would do fine in a job interview with you.
I do think that the tests won't give you a good view of a persons programming skills. Have a look at Joel's interviewing Guide:
http://www.joelonsoftware.com/articles/fog0000000073.html
He talks about two things when it comes to possible candidates: are they smart AND do they get the job done (now that's a powerful combination).Let your candidates talk a bit about projects they did or what they're toying around with at home. Find out if they are passionate about programming. Some experience is nice of course, just don't ask them to do tricks.
Q1 also has a potential InvalidCastException on the item.FindControl() line.
I don't think Q1 or Q2 are outside the realms of being too hard, even for non C# users. Any level code should be able to see that you should be using a boolean for active, and only using one if statement.
Q3 though atleast needs comments as someone else noted. That's not basic code, especially if you're targeting non-C# users with it too.
In question 2 for better modularity I would suggest passing the count of lsvnotificationList.Items as a parameter:
public void Question2(bool IsPostBack, int listItemsCount)
{
if (!IsPostBack || listItemsCount == 0)
BindlistviewNotification();
}

Categories

Resources