So, I am geocoding addresses from the Google Places API. There are 38 Google address component types, and we have ~5 in-house address component types, so I need a system of mapping a number of Google types to our in-house types, with fallbacks.
For example:
var neighbourhood = googleResponse.neighborhood || googleResponse.sublocality_level_2 || googleResponse.sublocality_level_1
What is the best/cleanest/most efficient way to do this? Basically, I need to assign a var to some returned value, unless that returned value is undefined, and then move down the chain.
I think your approach is sound - using the short-circuiting ORs feels a lot cleaner than having some sort of branching statement to me. My two recommendations would be:
You should probably add some kind of hard-coded value (an empty string, perhaps? Depends on your use case) as a final fallback, so that if all of the options aren't found, you don't end up with the variable being set to something unexpected. I think being 100% explicit about all the possible things that could be returned is always a good practice.
I'd recommend pulling that logic out into a function, so that if you want to reuse it elsewhere it'll be more maintainable. Even if you don't think you'll need to use it again, it's still worth doing in case you change your mind later on - having to go through and replace every instance of a piece of code is incredibly tedious! It also makes your code a lot easier to test - you can pass in a hard-coded googleResponse and check that the output matches your expectations.
So my approach would probably look something like this:
function getNeighborhood(googleResponse) {
return googleResponse.neighborhood
|| googleResponse.sublocality_level_2
|| googleResponse.sublocality_level_1
|| "";
}
var neighborhood = getNeighborhood(googleResponse);
EDIT:
In response to your comment, there's a couple of options I can think of for values that have to be concatenated.
If it's just a matter of "everything or nothing", you could write this quite elegantly with a ternary expression:
function getStreet(googleResponse) {
return googleResponse.street_number && googleResponse.route
? googleResponse.street_number + googleResponse.route
: "";
}
However, if you start trying to nest these with fallbacks, it's going to get very unreadable very fast. At that point, you're better off just relying on a if/else if/else - it's a bit long winded, but it's comprehensible, and that's more important in my eyes.
function getStreet(googleResponse) {
if (googleResponse.street_number && googleResponse.route) {
return googleResponse.street_number + googleResponse.route;
}
else if (/* fallback */) {
return /* concat here */;
}
else {
// Make sure to always return a value, even if all of
// the other fallbacks fail!
return "";
}
}
Related
I'd like to know which is considered a best practice when naming predicates in a negative condition.
I'm familiar with the convention of prepending is to the name of a predicate function to express that it returns a true or false value. For example, isGreaterThanFifty(120) clearly expresses the intent of the predicate function, that it will return true if the condition is met. Conversely, should we say !isGreaterThanFifty(120) when we want the negative condition, or would it be better to say isNotGreaterThanFifty(120)?
Should we create a predicate function that expresses:
the positive case (e.g. isValid()) and then use it with the ! (e.g. !isValid()) to negate it when using it
the negative case (e.g isInvalid() or isNotValid()) since that is how we are using it
For example,
if (!isValid(data)) {
return new Error();
}
// do something if it is valid
compared with
if (isNotValid(data)) {
return new Error();
}
// do something if it is valid
I'm looking for code that is more readable and expresses it's intent clearly.
I'm aware that some languages like Ruby allow us to use unless instead of if conditions or even append ? to the end of a function, but most languages do not. So my question is geared towards those languages like JavaScript that do not have such syntax.
There isn't a convention around this that I am aware.
And it should be driven by your actual need, for example are you going to make this call from more than one place (where it actually would benefit the code)? And are you possibly putting a bunch of predicates together, this could affect readability for example: (!isValid()) looks similar to (isValid()) which is why some prefer to use the full condition: (isValid() == false).
Or better yet putting the false on the left which can help prevent accidentally re-assigning a value when attempting to do a condition:
ie: false == isValid vs isValid == false which can be typo-ed or accidentally be replaced by a single = which would be bad news bears.
Use necessity as your driver and also always consider the future you (coming back to the code) and of course, always think of your Teammates.
I find negative names such as isNotValid confusing.
It is OK to use a negative name for a function in a negative context, but if isNotValid() is later used in a positive check, than you get !isNotValid(data). I find double negativity very confusing when reading other peoples code. So, to support future use and positive usage as well I'd go with isValid
I wonder if its considered a bad prcatice to return values of different type for the function. Consider the code:
function getInterval() {
var interval = getIntervalValueFromLocalStorage();
if (interval < 0) {
return false;
}
return interval;
}
So whenever I need the interval that function returns I can write
var interval = getInterval();
if (interval) {
//do some staff
}
In this case:
function getInterval() {
return getIntervalFromLocalStorage();
}
I will have to check if the interval is less than 0 and it doesn't seem very neat
Is it bad practise to return values of different types from a function?
Yes, it certainly is. While necessary in some cases, it makes semantic reasoning about your code harder, which is important for maintainability and correctness. And it also makes it harder for the compiler to optimise.
In your specific case, you should rather return 0 instead of false when the interval id is not valid.
There is no clear objective answer to this but here is my take on it.
There are essentially two considerations here: performance and readability/maintainability.
For performance always taking the same argument types and returning the same types can have a big impact (for example: http://www.html5rocks.com/en/tutorials/speed/v8/). In practice these differences are often ignorable unless you need fast code.
With regards to maintainability consistent return values do also help (in my opinion). The one exception I make is returning null which is what I would do in your case.
I'd recommend avoiding even those if reasonably possible. For instance a getCurrentUser() function could return a AnonymousUser instance rather than null when no user is logged in. This avoids a lot of null checks and the bugs associated with forgetting them.
So in short: Avoid returning different types whenever reasonably possible.
I am writing a Safari extension, and would like to detect what page (url) I am currently on, and do things accordingly.
Right now my code looks something like:
if (linkHas("facebook.com")) {...}
else if (linkHas("google.com")) {...}
else if (linkHas("yahoo.com")) {...}
where linkHas() is a function that basically returns 1 if it has the parameter, and 0 otherwise.
Is it possible to write this one single switch statement? I've read somewhere that switch statements are implemented as hash tables if there are more than 5 options. For a small script like mine, the speed probably doesn't really matter much here, I'm really just trying it as an exercise.
The simple, and straight answer is no.
The switch expression has to be/return a value, that is evaluated against the value of each case. As JCOC611 has actually demonstrated, it can be done, but I beg you, don't :)
There is probably definitely a better way of implementing what you're after, but that wasn't your question, so I'll leave it at that.
EDIT
In fact, let me show you a better way.
function doFacebookStuff() {
console.log('Hello Facebook!');
}
function doGoogleStuff() {
console.log('Hello Google!');
}
function doYahooStuff() {
console.log('Hello Yahoo!');
}
var domainActions = {
'facebook.com': doFacebookStuff,
'google.com': doGoogleStuff,
'yahoo.com': doYahooStuff
}
var matched = Object.keys(domainActions).filter(function(domain) {
if (linkHas(domain)) {
domainActions[domain]();
return true;
}
});
console.log('matched domains:', matched);
You can also replace .filter() with .some(), to have it stop at the first match it finds.
Edit: Disclaimer: the following is something you should not do, but is there for reference purposes only. Don't let people tell you you can't, but listen when they say you shouldn't.
The very naive way:
switch(true){
case linkHas("facebook.com"):
// ...
break;
case linkHas("google.com"):
// ...
break;
case linkHas("yahoo.com"):
// ...
break;
}
This has absolutely no performance benefits though. In fact, it might be slower if all the functions are evaluated before the equality tests are performed.
The long way would be to refactor linkHas to be getLinkDomain and check on whatever that returns.
In fact, lets do that. Using the convenient function extractDomain, written by lewdev, you can:
var domain = extractDomain(link);
switch(domain){
case "facebook.com":
// ...
break;
//...
}
Create an "enumeration" of domains to avoid magic strings.
Create a function "getDomain" that returns one of said enumeration.
Create your own hash table called "actions" using an object literal, keyed on said enumeration values. Hash table values can be functions containing the logic to run for that key.
Then write:
actions[getDomain()]();
I have recently learned that you can use a neat switch statement with fallthrough to set default argument values in Javascript:
function myFunc(arg1, arg2, arg3) {
//replace unpassed arguments with their defaults:
switch (arguments.length) {
case 0 : arg1 = "default1";
case 1 : arg2 = "default2";
case 2 : arg3 = "default3";
}
}
I have grown to like it a lot, since not only is it very short but it also works based on parameters actually passed, without relying on having a special class of values (null, falsy, etc) serve as placeholders as in the more traditional versions:
function myFunc(arg1, arg2, arg3){
//replace falsy arguments with their defaults:
arg1 = arg1 || "default1";
arg2 = arg2 || "default2";
arg3 = arg3 || "default3";
}
My inital though after seeing the version using the switch was that I should consider using it "by default" over the || version.
The switch fallthough makes it not much longer and it has the advantage that it is much more "robust" in that it does not care about the types of the parameters. In the general case, it sounds like a good idea to not have to worry about what would happen with all the falsy values ('', 0, null, false ...) whenever I have to make a function with default parameters.
I would then reserve the arg = arg || x for the actual cases where I want to check for truthyness instead of repurposing it as the general rule for parameter defaulting.
However, I found very few examples of this pattern when I did a code search for it so I had to put on my skeptic hat. Why didn't I find more examples of this idiom?
Is it just now very well known?
Did I not search well enough? Did I get confused by the large number of false positives?
Is there something that makes it inferior to the alternatives?
Some reasons that I (and some of the comments) could think of for avoiding switch(arguments.length):
Using named parameters passed via an object literal is very flexible and extensible. Perhaps places where more arguments can be optional are using this instead?
Perhaps most of the time we do want to check for truthyness? Using a category of values as palceholders also allows default parameters to appear in the middle instead of only at the end : myFunc('arg1', null, 'arg3')
Perhaps most people just prefer the very short arg = arg || "default" and most of the time we just don't care about falsy values?
Perhaps accessing arguements is evil/unperformant?
Perhaps this kind of switch case fallthrough has a bad part I didn't think about?
Are these cons enough to avoid using switch(arguments.length) as a staple default argument pattern or is it a neat trick I should keep and use in my code?
Since the question has been updated, it's really a matter of opinion. There are a number of javascript features that many people suggest avoiding, such as switch and ternary. This is why there is not a lot of information on some of those features.
The reason that suggestion is made is because many people miss-use those features and create problems in their code. The bugs are sometimes difficult to detect and it can be difficult for others to understand what your code is doing (particularly those unfamiliar with javascript or new programmers).
So if you like to do it that way, and you're not worried about the opinions (or skill level) of anyone working on your code. By all means, your approach will work. I have used the switch statement myself on occasion, and while I don't think it's really "good" or "bad", it's hard to find a situation that requires it.
You asked how I might go about this without an if-else chain:
function myFunc(args) {
var allArgs = {
arg1:"default1",
arg2:"default2",
arg3:"default3"
};
for (var key in args) {
allArgs[key] = args[key];
}
}
myFunc({arg1:null, arg3:'test'})
Just a guess, but Doug Crockford discourages the use of switch statements in 'JavaScript: the Good Parts.' His logic is that switch statements are a common source of bugs because it's difficult to locate them when using 'fall through' logic. It's easy to see when a case is triggered, but it's often difficult to determine if every case in a result set has been covered, especially if it's not your code.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I moved one years ago from classic OO languages such like Java to JavaScript. The following code is definitely not recommended (or even not correct) in Java:
if(dayNumber = getClickedDayNumber(dayInfo))
{
alert("day number found : " + dayNumber);
}
function getClickedDayNumber(dayInfo)
{
dayNumber = dayInfo.indexOf("fc-day");
if(dayNumber != -1) //substring found
{
//normally any calendar month consists of "40" days, so this will definitely pick up its day number.
return parseInt(dayInfo.substring(dayNumber+6, dayNumber+8));
}
return false;
}
Basically I just found out that I can assign a variable to a value in an if condition statement, and immediately check the assigned value as if it is boolean.
For a safer bet, I usually separate that into two lines of code, assign first then check the variable, but now that I found this, I am just wondering whether is it good practice or not in the eyes of experienced JavaScript developers?
I wouldn't recommend it. The problem is, it looks like a common error where you try to compare values, but use a single = instead of == or ===. For example, when you see this:
if (value = someFunction()) {
...
}
you don't know if that's what they meant to do, or if they intended to write this:
if (value == someFunction()) {
...
}
If you really want to do the assignment in place, I would recommend doing an explicit comparison as well:
if ((value = someFunction()) === <whatever truthy value you are expecting>) {
...
}
I see no proof that it is not good practice. Yes, it may look like a mistake but that is easily remedied by judicious commenting. Take for instance:
if (x = processorIntensiveFunction()) { // declaration inside if intended
alert(x);
}
Why should that function be allowed to run a 2nd time with:
alert(processorIntensiveFunction());
Because the first version LOOKS bad? I cannot agree with that logic.
I did it many times. To bypass the JavaScript warning, I add two parens:
if ((result = get_something())) { }
You should avoid it, if you really want to use it, write a comment above it saying what you are doing.
There is one case when you do it, with while-loops.
When reading files, you usualy do like this:
void readFile(String pathToFile) {
// Create a FileInputStream object
FileInputStream fileIn = null;
try {
// Create the FileInputStream
fileIn = new FileInputStream(pathToFile);
// Create a variable to store the current line's text in
String currentLine;
// While the file has lines left, read the next line,
// store it in the variable and do whatever is in the loop
while((currentLine = in.readLine()) != null) {
// Print out the current line in the console
// (you can do whatever you want with the line. this is just an example)
System.out.println(currentLine);
}
} catch(IOException e) {
// Handle exception
} finally {
try {
// Close the FileInputStream
fileIn.close();
} catch(IOException e) {
// Handle exception
}
}
}
Look at the while-loop at line 9. There, a new line is read and stored in a variable, and then the content of the loop is ran. I know this isn't an if-statement, but I guess a while loop can be included in your question as well.
The reason to this is that when using a FileInputStream, every time you call FileInputStream.readLine(), it reads the next line in the file, so if you would have called it from the loop with just fileIn.readLine() != null without assigning the variable, instead of calling (currentLine = fileIn.readLine()) != null, and then called it from inside of the loop too, you would only get every second line.
Hope you understand, and good luck!
If you were to refer to Martin Fowlers book Refactoring improving the design of existing code ! Then there are several cases where it would be good practice eg. long complex conditionals to use a function or method call to assert your case:
"Motivation
One of the most common areas of complexity in a program lies in complex conditional logic.
As you write code to test conditions and to do various things depending on various
conditions, you quickly end up with a pretty long method. Length of a method is in itself a factor that makes it harder to read, but conditions increase the difficulty. The problem
usually lies in the fact that the code, both in the condition checks and in the actions,
tells you what happens but can easily obscure why it happens.
As with any large block of code, you can make your intention clearer by decomposing it and
replacing chunks of code with a method call named after the intention of that block of code. > With conditions you can receive further benefit by doing this for the conditional part and
each of the alternatives. This way you highlight the condition and make it clearly what you > are branching on. You also highlight the reason for the branching."
And yes his answer is also valid for Java implementations. It does not assign the conditional function to a variable though in the examples.
I came here from golang, where it's common to see something like
if (err := doSomething(); err != nil) {
return nil, err
}
In which err is scoped to that if block only. As such, here's what I'm doing in es6, which seems pretty ugly, but doesn't make my rather strict eslint rules whinge, and achieves the same.
{
const err = doSomething()
if (err != null) {
return (null, err)
}
}
The extra braces define a new, uh, "lexical scope"? Which means I can use const, and err isn't available to the outer block.
You can do this in Java too. And no, it's not a good practice. :)
(And use the === in Javascript for typed equality. Read Crockford's The Good Parts book on JS.)
You can do assignments within if statements in Java as well. A good example would be reading something in and writing it out:
http://www.exampledepot.com/egs/java.io/CopyFile.html?l=new
The code:
// Copies src file to dst file.
// If the dst file does not exist, it is created
void copy(File src, File dst) throws IOException
{
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
It's not good practice. You soon will get confused about it. It looks similiar to a common error: misuse "=" and "==" operators.
You should break it into 2 lines of codes. It not only helps to make the code clearer, but also easy to refactor in the future. Imagine that you change the IF condition? You may accidently remove the line and your variable no longer get the value assigned to it.
you could do something like so:
if (value = /* sic */ some_function()){
use_value(value)
}