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 9 years ago.
Improve this question
I'm interested in how you guys lay out your Javascript objects/classes when they contain lots of functions, all of which need to be on the same 'level' (i.e. they need to remain as first level functions of the object).
So with a structure like this...
Namespace.class = {
abc: 1,
def: 2,
ghi: 3,
funcA: function(){
// Some logic
},
funcB: function(){
// Some logic
},
// Lots more functions
funcN: function(){
// Some logic
}
}
This can all get pretty unwieldy. How do you lay out these types of objects to make them readable, easy to maintain and quick for new developers to pick up?
My approach has been to organise everything in alphabetical order, so you know roughly where to go if you know a function's name.
But does it make more sense to group functions that are closely related in what they do and those that refer to eachother?
There are many approaches here and it depends on how exactly you interact with your code.
Some things to keep in mind:
1) If the code is unwieldy, a refactoring is probably overdue.
Consider breaking your class into smaller classes each dealing with different aspects of what the big class does. Split functionality in multiple namespaces if you use static functions rather than classes.
Consider splitting functionality over multiple files (one-class-per-file for example) and having a build process that combines and minifies your output.
2) Tools can help.
If you deal with large codebases it's probably a good idea to find an editor (or learn to use its functions better) that can help you deal with it. Your IDE will probably have some functionality to help you navigate the file structure better, like a file structure overview, or code regions, or objects view
3) Organize functions by what makes sense.
An alphabetic solution could make sense in some situations, but grouping by functionality is probably better. Putting exported methods all in one place is probably a good idea as well:
Namespace = function() {
var f1 = function() { };
var f2 = function() { }; // this is internal
// Exported methods
return {
f1 : f1
}
}();
4) Document your code.
While reading the code is invaluable in giving someone an in-depth understanding, code ducmentation is essential in having a first-glance understanding. It can also be useful to you during development because you don't have to remember all the quirks of your code.
5) Enforce a coding style that can help you.
Your coding style can help you find things in the code easier. If you always use the same spacing, put braces the same way, etc, finding a function definition can be as easy as Ctrl-f: myFunc:.
One approach is to modularize the class, and split it across multiple files. Typically this approach is used to provide plugins to a core class. jQuery is a great example of where the class has been extended using plugins.
When you're not interested in splitting the same class across multiple files, I find alphabetizing the function order helps.
In the end the order of the functions shouldn't matter so long as you have a good enough IDE that it lets you jump to the definition for that function.
God objects are an anti-pattern and a good indicator that you have some serious design flaws.
If you follow the single responsability principle and have a smart IDE that supports intellisense and other similar features, the investment for trying to keep everything ordered is not worth and not necessary since that would be the IDE's job to show all function definitions ordered in a panel for quick-access and to have a global overview.
If you really want to order your functions you could have an automated process that keeps your object literals structured.
However that doesn't mean you shouldn't have any coding standards. I also still organize my code in a way that makes sense e.g. private/public/priviledged members together.
Related
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 4 years ago.
Improve this question
I always use one array arguments to a function whenever I need more then 3 parameter.
Example: Consider a function call like this.
processSecondStage($stepTitle, $round, $entryId, $formId, $stepType, $stepAfterApproved, $assigneees, $stageToMove);
I always prefer the below one.
processSecondStage(array(
'stepTitle' => $title,
'round' => $round,
'stepAfterApproved' => $stepAfterApproved,
'entryId' => $_entryId,
'assigneees' => (array)$_POST['flow-asignee'],
'stageToMove' => $currentStep,
'formId' => $targetFormId,
'stepType' => 'approval'
));
Advantage (I might be wrong):
a) Can add more number of parameter
b) Readability
c) Order can be changed easily
d) Default parameter handling is easier
Disadvantage :
a) Code length is increase specially in case when we have less then 3-4 arguments.
Can anyone please help me Know more disadvantage of using the array parameter ?
Whenever I change other developer code (like I am going to do now), then I feel that there are some major disadvantage of using array as parameter because if that was not the case then it should have been a standard practice.
Although I have given example of PHP, but I find this in other language also on which I work.
Thank You.
Arrays are useful as a parameter when things you want to pass are closely related and do not make sense separately. A classical example is a Color that is defined by blue, green, red (and maybe gamma). Combining these parameters into an array (or object in javascript) allows you to swap it out easily.
Always using an array as the single parameter of a function makes you loose out on a parameter list an IDE can give you. For someone reading the code, it is quite a hell to figure out what needs to be passed to a function. It also opens the door to future creep (oh, this function was only making me coffee, but if I add another optional parameter it can also make me tea. Oh, and maybe I can let it make me dinner to. Why not add the functionality to order an attack helicopter too).
In a regular parameter list you can pass things by reference (function pushElement(array &$sortableArray, $element)). This is not expected in a regular array, if it is even possible.
The point about default values is kind of a moot point. Normal parameter lists allow type hinting and default values just fine:
function action(string $action = 'tickle', string $target = 'Polar bear') {
print "I {$action} a {$target}";
}
A single parameter as array probably only really shines when passing some kind of static configuration. You keep the configuration of something separate from the actual code using it, making it easier to modify the configuration. At the same time you leverage the fact that you do not have to send 20 parameters in a very specific order.
In your case the parameter list you give is wildly varied and long, which suggests that your function is doing way too much. Part of it should probably be moved to a constructor and part of it should probably be moved to some kind of Form class.
Parts of the topic are very much opinionated...
The problem you describe is not just parameters as a list vs a sequence of parameters. There are several problems that occur (with both in your example).
Tooling
Ordering of parameters
Semantics
Tooling is probably obvious: If you have only arrays as parameters, no IDE will know what is supposed to be inside. Okay, most IDEs won't know.
Ordering of parameters is usually dictated by the name of the function and/or its semantics. If you drawLine the canonical order of the parameters is ($from, $to). If there is no canonical order, there might be something else wrong with the code... (see below)
Semantics: If you have 3+ parameters (especially if you have way more), it is very likely, that the abstraction is wrong. For example let's assume you have a function createShirt($size="m", int $red, int $blue, int $green, Image $logo, $material="wool"): The order of attributes is arbitrary and the object produced (a shirt) may not need all of those parameters, but you can absolutely use this abstraction. I would much prefer the builder pattern, example:
$shirt = ShirtBuilder::create("m") // verifies m is a size
->setColor(new Color($red,$green,$blue)) // has type-hint color
->setImage($logo) // has type-hint
->setMaterial($material)
->build();
It absolutely is more verbose, but it is apparent you only have to call functions that are needed, you can validate set values at any point (read: function call). The build function could verify that the combination is valid and the Shirt object itself could even be immutable.
However, arrays absolutely do have their place and purpose. But usually it is "providing a list of things of the same type". If your array has only string-keys that are from a very small domain, you probably want an object.
Using objects will trigger questions such as "which parameters should belong to this object?". if there is no semantic reason for a true subset of parameters to appear together, you probably want the command pattern (command objects). and IDEs might provide all the wonders that make using those easy
tl;dr:
Using arrays to hold a list of heterogeneous parameters is probably an anti-pattern (might be warranted in some scenario/language).
Functions/methods with more than 3 parameters suggest too little abstraction (there might be reasons). Use appropriate design patterns.
This question is about ES6 not about global variables.
When the new ES2015 export or export default were introduced. They were made so that you can import/get the same variables, values or items somewhere else using import. So I have a simple question. Why should we use export and import instead of just making a simple object of a class and getting items through it or just making static or global variables?
I know the fact that it can be used to make your code much cleaner and also to put the code easily into multiple files but let's just assume we have first.js and second.js and we have a variable called names in the first.js that we want to get in the second.js. Now you can either do that with import and export or by making an object in the second.js and accessing our variable by that object. So why is it better to use export and import?
export was introduced to be used alongside import (you need to explicitly declare what you need to later import), as part of the ES2015 module standard.
Before these standard modules were implemented, splitting up Javascript code into multiple files and not have all objects pollute the global object was only possible using sort short of non-standard module definition and/or module loaders like RequireJS. The simplest case was to wrap your code in Immediately Invoked Functions. ES6/2015 just standardize Javascipt modules.
Now you asked why not just have Javascript objects even in many files? The answer to that is namespacing
Actually - you make a good point.
namespace stuff is in C++. There are lots of people who think it is cool to have a namespace indicator in front of everything they use.
So, instead of saying { cout << my_string << endl; }, their whole program has { std::cout << my_string << std::endl; }.
Sometimes you see stuff like { disk::io::byte::bit::atom::neutron::quark::say_hi(2) }. And, the guy who wrote that thinks he's a super developer.
But, as they are purist, it more likely you will see { std::cout << myString << endl; } because camel case is so much more preferential than human readable strings.
Now, in node.js I am always doing something like const ClassFromMod = require('mod-with-class'). In the file, you have to say module.exports = ClassDeclaredInHere. I always do this, because really, is there any other way provided?
Or you can do this const {ClassFromMod} = require('mod-with-class').
Then you have to have, module.exports.ClassFromMod = ClassDeclaredInHere.
So, doing the same thing in the browser is sort of OK. But, now global contexts and local contexts are harder to work with - really. Just a little harder sharing things between modules when you have to. But, not to worry almost all of the time people partitions their modules just right. That's because they are people - in fact the sort of people who are more cautious than those in charge of nuclear reactors - because those people do some web programming. So, no Chernobyl when it comes to partitioning modules. Right?
Now, you can get your hands into a class def. And, the class is itself something of a namespace.
So, then why is there not a global registry of classes? Only that maybe different companies (individual developers) will use the same name for two remotely different classes. But, likely there would be some way around that.
One way might be to assign classes to uses (sort of name spacey). But, it might be more categorical. Like "engine" for something with a car feature, or "engine" for something that runs a script. Programming languages might have something like "talking about cars here". What would that be like?
start>> talking about cars <
let bval = engine.rev()
if ( bval ) {
<about scripts> engine.run("small program")
}
<<stop talking about car
That's an idea. Looking at it, I don' like it. It's sort of like "with" that lots of languages use.
So, with new strictures imposed on the programming environments, you get bugs and scope troubles that add to your long long long day. But, you should get that your question drawn from clear thinking is in some sense being steamrolled by a small group of people who can. And, you can take out the trash for them.
So, what about identifying objects by features and enabling sort of a flat namespace management? Could be driven by AI. Could have been done thirty years ago. But, now is now. But, the future exists for correcting the mistakes of the past.
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 7 years ago.
Improve this question
I have been reading about some good practices in JavaScript and one of them was Unobtrusive JavaScript. The first point caught my attention
Separation of functionality (the "behavior layer") from a Web page's structure/content and presentation
On the wiki page, one of the examples is that you should bind actions to events in JS files instead of in the HTML. This example
<input type="text" name="date" id="date" />
...
window.onload = function() {
document.getElementById('date').onchange = validateDate;
};
is favored over
<input type="text" name="date" onchange="validateDate()" />
However, I would say I'd prefer the second code with onchange attribute over the first one. My reasons for this are
It is easily readable and immediately clear what will happen on change (or any other event) on that element.
I don't have to got through JavaScript files and look where (and whether) the onchange event is bind and whether there are some other events such as click defined for #date.
Frameworks such as AngularJS have ng-click and is mixing up HTML structure with JS. Why shouldn't I?
The disadvantages of not using unobtrusive javascript that I have read about are
Polluting global namespace.
Creating long and unreadable inline code.
If the code for an event changes, you have to change it only in one place - that is in a JS file.
But I think that the disadvantages can be solved.
Instead of polluting namespace, create the app in one variable so the code would look like onchange="app.validateDate()" and no polluting would happen.
Inline code would not be written and would be separated in a function in JS file, then it'd be called like onclick="app.action();".
Isn't it the same as using a function in onclick attribute? Because in the end you have to make a change just in one function in both approaches whether it is $('input').change(function () {/* ... change ... */}); or app.action = function () {/* ... change ... */}.
So is it actually still considered a good practice?
This is a very broad topic and heavily opinion based. There is no one answer to everything. However, here are some observations:
You are polluting the namespace whatever you do. app.validateDate pollutes the namespace just as validateDate does, just by virtue of needing to have a globally accessible function name. In complex modern sites, there are tons of scripts competing for global names. Ideally you're never exposing any name globally, not even a namespace name.
.onclick = handler is not great either. You'd want:
document.getElementById('date').addEventListener('change', function () { .. });
This is even less obtrusive and allows several scripts to bind event listeners to the same element. Again, in complex modern sites one of the highest priorities you can have is to ensure nobody is stepping on anyone else's feet. You never know who else might be interested in the change event of that element in the future.
It is still more code to write it inline than elsewhere. Longer HTML code that is. HTML can already be very verbose. Anything you can move elsewhere you should. Reducing the amount of code in any one particular file is an art in itself and important for readability. Yeah, it's "just one more attribute"... on top of all the other attributes and elements and inline declarations you're also not avoiding. It's just piling up, and that's how code gets messy and unreadable and unmaintainable.
Reusability: document.getElementById(..).addEventListener can be written once in an external file and automagically reused across many different pages. <.. onclick=".."> needs to be repeatedly written every single time. DRY your code.
For tiny projects it often hardly matters. But again, sites are getting more and more complex. Business needs demand constant changes. Just one more analytics script, just one more Javascript based social widget, now change it all back, now keep all the versions of dependencies in sync, now rip it all out again and redesign for our 2.0 launch next week. Do it all with 10 other people in parallel without nuking each others code on every build or needing long sessions of resolving git-merge conflicts. In such an environment, every little bit of decoupling and indirection and flexibility helps.
Since you mention Angular:
Angular avoids some of these issues by employing a completely different template parsing model. When you write onclick=foo, then you need to bind to a global function name. However, when Angular does ng-click=foo, foo is a locally scoped entity in an ng-scope. It's not a global name. Angular separates between a controller and a view, where the controller essentially exposes a specific API on the $scope object which the view can use; both the controller and the view are still interchangeable as long as the specified API contract is kept (meaning as long as the $scope object keeps the same attributes).
All ng directives are evaluated against a custom scoping and evaluation engine which does not have much to do with Javascript's default modus operandi.
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 4 years ago.
Improve this question
The more I delve into javascript, the more I think about the consequences of certain design decisions and encouraged practices. In this case, I am observing anonymous functions, a feature which is not only JavaScript-provided, but I see strongly used.
I think we can all agree on the following facts:
the human mind does not deal with more than 7 plus minus two entities (Miller's law)
deep indentation is considered bad programming practice, and generally points out at design issues if you indent more than three or four levels. This extends to nested entities, and it's well presented in the python Zen entry "Flat is better than nested."
the idea of having a function name is both for reference, and for easy documentation of the task it performs. We know, or can expect, what a function called removeListEntry() does. Self-documenting, clear code is important for debugging and readability.
While anonymous functions appears to be a very nice feature, its use leads to deeply nested code design. The code is quick to write, but difficult to read. Instead of being forced to invent a named context for a functionality, and flatten your hierarchy of callable objects, it encourages a "go deep one level", pushing your brain stack and quickly overflowing the 7 +/- 2 rule. A similar concept is expressed in Alan Cooper's "About Face", quoting loosely "people don't understand hierarchies". As programmers we do understand hierarchies, but our biology still limits our grasping of deep nesting.
I'd like to hear you on this point. Should anonymous functions be considered harmful, an apparent shiny syntactic sugar which we find later on to be salt, or even rat poison ?
CW as there's no correct answer.
As I see it, the problem you're facing is not anonymous functions, rather an unwillingness to factor out functionality into useful and reusable units. Which is interesting, because it's easier to reuse functionality in languages with first-class functions (and, necessarily, anonymous functions) than in languages without.
If you see a lot of deeply nested anonymous functions in your code, I would suggest that there may be a lot of common functionality that can be factored out into named higher-order functions (i.e. functions that take or return ("build") other functions). Even "simple" transformations of existing functions should be given names if they are used often. This is just the DRY principle.
Anonymous functions are more useful functionally than they are harmful legibly. I think that if you format your code well enough, you shouldn't have a problem. I don't have a problem with it, and I'm sure I can't handle 7 elements, let alone 7 + 2 :)
Actually, hierarchies help to overcome 7+/-2 rule the same way as OOP does. When you're writing or reading a class, you read its content and nothing of outside code so you are dealing with relatively small portion of entities. When you're looking at class hierarchies, you don't look inside them, meaning then again you are dealing with small number of entities.
The same if true for nested functions. By dividing your code into multiple levels of hierarchy, you keep each level small enough for human brain to comprehend.
Closures (or anonymous functions) just help to break your code into slightly different way than OOP does but they doesn't really create any hierarchies. They are here to help you to execute your code in context of other block of code. In C++ or Java you have to create a class for that, in JavaScript function is enough. Granted, standalone class is easier to understand as it is just easier for human to look at it as at standalone block. Function seems to be much smaller in size and brain sometimes think it can comprehend it AND code around it at the same time which is usually a bad idea. But you can train your brain not to do that :)
So no, I don't think anonymous functions are at all harmful, you just have to learn to deal with them, as you learnt to deal with classes.
Amusingly, JavaScript will let you name "anonymous" functions:
function f(x) {
return function add(y) {
return x+y;
};
}
I think closures have enormous benefits which should not be overlooked. For example, Apple leverages "blocks"(closures for C) with GCD to provide really easy multithreading - you don't need to setup context structs, and can just reference variables by name since they're in scope.
I think a bigger problem with Javascript is that it doesn't have block scope(blocks in this case referring to code in braces, like an if statement). This can lead to enormous complications, forcing programmers to use unnecessary closures to get around this Javascript design limitation.
I also think anonymous functions (in latest languages often referred as closures) have great benefits and make code often more readable and shorter. I sometimes am getting really nuts when I have to work with Java (where closures aren't first class language features).
If indentation and too many encapsulated function-variables are the problem then you should refactor the code to have it more modular and readable.
Regarding java-script I think that function-variables look quite ugly and make code cluttered (the encapsulated function(...){} string makes java-script code often less readable). As an example I much prefer the closure syntax of groovy ('{}' and '->' chars).
If a function is not understandable without a name, the name is probably too long.
Use comments to explain cryptic code, don't rely on names.
Who ever came up with the idea of requiring functions to be bound to identifiers did every programmer a disservice. If you've never done functional programming and you're not familiar with and comfortable with functions being first-class values, you're not a real programmer.
In fact, to counter your own argument, I would go so far as to consider functions bound to (global) names to be harmful! Check Crockford's article about private and public members and learn more.
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.
I find that what not to do is a harder lesson to learn than what should be done.
From my experience, what separates an expert from an intermediate is the ability to select from among various seemingly equivalent ways of doing the same thing.
So, when it comes to JavaScript what kinds of things should you not do and why?
I'm able to find lots of these for Java, but since JavaScript's typical context (in a browser) is very different from Java's I'm curious to see what comes out.
Language:
Namespace polluting by creating a large footprint of variables in the global context.
Binding event handlers in the form 'foo.onclick = myFunc' (inextensible, should be using attachEvent/addEventListener).
Using eval in almost any non-JSON context
Almost every use of document.write (use the DOM methods like document.createElement)
Prototyping against the Object object (BOOM!)
A small one this, but doing large numbers of string concats with '+' (creating an array and joining it is much more efficient)
Referring to the non-existent undefined constant
Design/Deployment:
(Generally) not providing noscript support.
Not packaging your code into a single resource
Putting inline (i.e. body) scripts near the top of the body (they block loading)
Ajax specific:
not indicating the start, end, or error of a request to the user
polling
passing and parsing XML instead of JSON or HTML (where appropriate)
Many of these were sourced from the book Learning JavaScript Design by Addy Osmati: https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/ch06.html
edit: I keep thinking of more!
Besides those already mentioned...
Using the for..in construct to iterate over arrays
(iterates over array methods AND indices)
Using Javascript inline like <body onload="doThis();">
(inflexible and prevents multiple event listeners)
Using the 'Function()' constructor
(bad for the same reasons eval() is bad)
Passing strings instead of functions to setTimeout or setInterval
(also uses eval() internally)
Relying on implicit statements by not using semicolons
(bad habit to pick up, and can lead to unexpected behavior)
Using /* .. */ to block out lines of code
(can interfere with regex literals, e.g.: /* /.*/ */)
<evangelism>
And of course, not using Prototype ;)
</evangelism>
The biggest for me is not understanding the JavaScript programming language itself.
Overusing object hierarchies and building very deep inheritance chains. Shallow hierarchies work fine in most cases in JS.
Not understanding prototype based object orientation, and instead building huge amounts of scaffolding to make JS behave like traditional OO languages.
Unnecessarily using OO paradigms when procedural / functional programming could be more concise and efficient.
Then there are those for the browser runtime:
Not using good established event patterns like event delegation or the observer pattern (pub/sub) to optimize event handling.
Making frequent DOM updates (like .appendChild in a loop), when the DOM nodes can be in memory and appended in one go. (HUGE performance benefit).
Overusing libraries for selecting nodes with complex selectors when native methods can be used (getElementById, getElementByTagName, etc.). This is becoming lesser of an issue these days, but it's worth mentioning.
Extending DOM objects when you expect third-party scripts to be on the same page as yours (you will end up clobbering each other's code).
And finally the deployment issues.
Not minifying your files.
Web-server configs - not gzipping your files, not caching them sensibly.
<plug> I've got some client-side optimization tips which cover some of the things I've mentioned above, and more, on my blog.</plug>
browser detection (instead of testing whether the specific methods/fields you want to use exist)
using alert() in most cases
see also Crockford's "Javascript: The Good Parts" for various other things to avoid. (edit: warning, he's a bit strict in some of his suggestions like the use of "===" over "==" so take them with whatever grain of salt works for you)
A few things right on top of my head. I'll edit this list when I think of more.
Don't pollute global namespace. Organize things in objects instead;
Don't omit 'var' for variables. That pollutes global namespace and might get you in trouble with other such scripts.
any use of 'with'
with (document.forms["mainForm"].elements) {
input1.value = "junk";
input2.value = "junk";
}
any reference to
document.all
in your code, unless it is within special code, just for IE to overcome an IE bug. (cough document.getElementById() cough)
Bad use of brace positioning when creating statements
You should always put a brace after the statement due to automatic semicolon insertion.
For example this:
function()
{
return
{
price: 10
}
}
differs greatly from this:
function(){
return{
price: 10
}
}
Becuase in the first example, javascript will insert a semicolon for you actually leaving you with this:
function()
{
return; // oh dear!
{
price: 10
}
}
Using setInterval for potentially long running tasks.
You should use setTimeout rather than setInterval for occasions where you need to do something repeatedly.
If you use setInterval, but the function that is executed in the timer is not finished by the time the timer next ticks, this is bad. Instead use the following pattern using setTimeout
function doThisManyTimes(){
alert("It's happening again!");
}
(function repeat(){
doThisManyTimes();
setTimeout(repeat, 500);
})();
This is explained very well by Paul Irish on his 10 things I learned from the jQuery source video
Not using a community based framework to do repetitive tasks like DOM manipulation, event handling, etc.
Effective caching is seldomly done:
Don't store a copy of the library (jQuery, Prototype, Dojo) on your server when you can use a shared API like Google's Libraries API to speed up page loads
Combine and minify all your script that you can into one
Use mod_expires to give all your scripts infinite cache lifetime (never redownload)
Version your javascript filenames so that a new update will be taken by clients without need to reload/restart
(i.e. myFile_r231.js, or myFile.js?r=231)