I have some procedural javascript code that I have written for an open-source application and I'd Like to refactor it into OOP and since I have very little experience with javascript frameworks I have trouble finding a one suitable for my needs, though I haven't tried anything yet, I just read about AngularJS, Backbone.js and Knockout.
I want to structure the code, because, at the moment, there's a mess, global variables and functions scattered around.
I have to mention that all the business logic is handled at the server level, so the client-side code handles just the UI using the data it receives or requests from the server.
The code can be found here:
https://github.com/paullik/webchat/blob/asp.net/webchat/Static/Js/chat.js
Do you have any suggestions?
Object-Oriented JavaScript is not necessarily the answer to all your
problems.
My advice is to be careful the choice you pick on this topic.
In practice, OO-JS can add more complexity to your code for the sake of trying to be more like traditional object-oriented languages. As you probably know, JS is unique.
It is important to know that there are Design Patterns that will structure your code and keep implementation light and flexible.
It is Design Patterns that I see structuring advanced JS
implementations, not OO. To paraphrase Axel Rauchmeyer - "Object
Oriented methodology does not fit into basic JavaScript syntax, it is
a twisted and contorted implementation, and JS is far more expressive
with out it."
The root of this analysis boils down to the fact that JS has no class. In essence, since everything is an object, you already have object-oriented variables and functions. Thus the problem is slightly different than the one found in compiled languages (C/Java).
What Design Patterns are there for JavaScript?
An excellent resource to check is Addy O' Somani and Essential Design Patterns.
He wrote this book on Design Patterns in JavaScript.
But there is more... much more.
A. require.js - There is a way to load modules of JS code in a very impressive way.
These are generally called a module loaders, and are widely considered the future of loading js files since they optimize performance at runtime. yepnope and others exist. Keep this in mind if you are loading more than a few js files. (moved to top by request).
B. MVC - There are dozens of Model View Controller frameworks to help you structure code.
It is a Pattern, but may be unreasonable for your purposes. You mentioned backbone, knockout and angular... Yes. These can do the trick for you, but I would be concerned that they might be 1) high learning-curve, and 2) overkill for your environment.
C. Namespace or Module Pattern. Are probably the most important for your needs.
To solve global variables just wrap them in a namespace and reference that.
These are very good patterns that give rise to module loaders.
D. Closure - You mentioned OO JS. On piece of this that is useful is the notion of closures to provide yourself with... private members. At first this is a cryptic idea, but after you recognize the pattern, it is trivial practice.
E. Custom Events - It becomes very important to not use hard references between objects. Example: AnotherObject.member; This is because it will tightly couple the two objects together and make both of them inflexible to change. To solve this, trigger and listen to events. In traditional Design Patterns this is the Observer. In JS it is called PubSub.
F. The Callback - The callback pattern is what enabled AJAX and it is revolutionizing development in terms of Window 8, Firefox OS, and Node.js - because of something called non-blocking-io. Very important.
Do not be afraid. This is the direction to go for long-term and advanced JavaScript implementations.
Once you recognize the patterns, it is down hill from there.
Hope this helps.
Related
I'm trying to implement an application using node.js and other related technologies. Heading from java land polymorphism but natural, but for the classical programmer node works differently.
The application will load new code during run-time provided by the user. In order for the main core to use this code "we" need to agree on some kind of a convention. Knowing how new Node is I wasn't that surprised that I didn't find the answer. The problem is this issue is rather vague in JS too.
Requirements:
Strong decoupling.
loading new code in run-time.
The solution should be applicable so I can share as much code as possible with the browser.
Update:
I did fiddle around with duck-typing, I've also encountered ideas from Clojure in regards to protocol based implementation.
I would appreciate some code in the answer.
JavaScript, just like most other scripting languages (i.e. no compile-time type checking) does polymorphism through duck typing.
If you're from Java-land you're probably looking for Dependency Injection which generally provides uber decoupling. You can probably use google to find a good dependency injection framework for Node, like this one.
Although truthfully you can probably just make a single Javascript/Coffeescript file that does all the wiring and config loading.
Because of the flexibility of Javascript just about every form polymorphism has been implemented (traits, interfaces, inheritance, prototypes). Each have their advantages/disadvantages but almost all are runtime check (if any) and not compile time.
Personally I would probably just use either Coffeescripts inheritance, traits.js or Javascript's builtin prototype chain.
EDIT: However since you're talking about allowing users to extend the system then callbacks and/or custom events are the preferred approach (i.e. higher order functional programming and event-bus). If you're looking for something substantial like a plugin system then loader-js looks rather complete (tip of the hat to #Larry Battle).
Compared with Java/C#/C/C++ projects, we often see web frontend projects (html/css/javascript) are too complex to read and maintain. So, can we summarize some best practices for web frontend projects? The goal is readability, modularization, easy to maintain.
Accomplishing this takes a mix of good patterns and knowing what fights not to fight.
CSS is best if it's factored out, efficient, and cleanly formatted. No overthinking necessary here, CSS is a beautiful language, I like to keep it simple. For example see my answer here: MVC 3, CSS, Razor and Visual Studio 2010
Javascript can definitely be organized by using some kind of object based pattern: http://www.klauskomenda.com/code/javascript-programming-patterns/. I use something close to "Custom Objects" from that link. With YUI we have built in namespaces, with jQuery we can add them: Is it possible to create a namespace in jQuery?. As far as separating out content, separate objects and related functionality in their own javascript files and include them on the pages where they're needed. For optimization, you can compile all the scripts on any page down into one script. YUI 3 has a great dependency loading mechanism - use that. For jQuery, you can use one of the many dependency loaders: Javascript loaders with jQuery
As far as HTML, I think MVC is the most popular patter these days. Using any modern mvc framework will lay things out for you well. (Ex. rails, any java ones, asp.net mvc, pylons, etc.)
Well, for now, web development has many approaches and there's no standard way of doing things.
By the way, since JavaScript doesn't support some OOP features like actual classes or namespacing, but prototyping, you need to know that this isn't a good start for crearting good and large moduralized front-end Web projects.
Although there're limitations, you can use prototyping in order to leverage some kind of pseudo-OOP design. That's you can create a component-oriented user interface based on inheritance of some abstract hierarchy defining common behaviors and visualizations.
Keeping in mind one of most important points in any modern development is reuse and scalability, I think using pseudo-OOP with prototyping should be fine to avoid bad practices and enforce maintainibility, readability and moduralization.
For example, you can simulate namespacing with prototypes. This is achieved by creating anonymous objects where their members are anonymous functions acting as getters (properties) where their return type is the prototype of some actual "class" - there're other ways to achieve this same result -:
http://www.codeproject.com/KB/scripting/jsnamespaces.aspx
Or you can simulate polymorphism:
http://www.codeproject.com/KB/scripting/edujini_007_JavaScript_OO.aspx
I could add more references, but I believe you got it: it's more like trying to export actual OOP approaches to JavaScript and use same design patterns that have been in the ground for a lot of years!
Another point should be you can get this moduralization by extending existing JavaScript frameworks like jQuery, Prototype, MooTools, Microsoft AJAX (this is a good start because it has many built-in OOP features like namespaces, inheritance, polymorphism...).
Coming from Java, I'm wondering if a Java best practice applies to JavaScript.
In Java, there's a separation of interface and implementation, and mixing them up is considered a bad practice. By the same token, it is recommended to hide implementation details of your library from end developers.
For example, log4J is one of the most popular logging libraries out there but it is recommended to write code to the slf4j library or the Commons Logging library that "wraps" log4j. This way, if you choose to switch to another logging framework such as logback, you can do so without changing your code. Another reason is that you, as a user of a logging library, how logging is done is none of your concern, as long as you know what logging does.
So back to JavaScript, most non-trivial web applications have their own custom JavaScript libraries, many of which use open source libraries such as jQuery and dojo. If a custom library depends on, say jQuery, not as an extension, but as implementation, do you see the need to add another layer that wraps jQuery and makes it transparent to the rest of JavaScript code?
For example, if you have the foo library that contains all your custom, front-end logic, you'd introduce the bar library that just wraps jQuery. This way, your foo library would use the bar library for jQuery functions, but it is totally oblivious to jQuery. In theory, you could switch to other libraries such as dojo and google web toolkit without having a big impact on the foo library.
Do you see any practical value in this? Overkill?
Although it makes sense from a theoretical standpoint, in practice I'd say it's overkill. If nothing else for these two reasons:
Anything that adds to the size of
the request (or adds more requests)
is bad - in web world, less is more.
If you're using say jQuery, the
chances of you switching to
something like Mootools is (imho) slim to none. From what I've seen, the top libraries each aim to solve different problems (at least in the case of Mootools and jQuery - see this great doc for more info on that). I'd assume that you'd incur a tremendous amount of headache if you were to try to implement a middleware library that could easily switch between the two.
In my experience and being a Java developer myself, sometimes we tend to take the whole "abstraction" layer pattern too far, I've seen implementations where someone decided to completely abstract a certain framework just for the sake of "flexibility" but it ends up making things more complicated and creating more code to maintain.
Bottom line is you should look at it on a case by case basis, for example you wouldn't try to create an abstraction layer on top of struts, or on top of JPA, just in case you then go to a different framework (which I've rarely seen done).
My suggestion is, regardless of the framework you are using, create objects and components that use the framework internally, they should model your problem and be able to interact between them without the need of any specific framework.
Hope this helps.
There are a lot of good answers here, but one thing I don't see mentioned is feature sets. If you try to write a library to wrap the functionality provided by, say, jQuery, but you want to be able to easily swap out for something like prototype, you have a problem. The jQuery library doesn't provide all the features prototype provides, and prototype doesn't provide all the features jQuery provides. On top of that, they both provide their features in radically different ways (prototype extends base objects -- that's damn near impossible to wrap).
In the end, if you tried to wrap these libraries in some code that adds 'abstraction' to try to make them more flexible, you're going to lose 80% of what the frameworks provided. You'll lose the fancy interfaces they provide (jQuery provides an awesome $('selector') function, prototype extends base objects), and you'll also have to decide if you want to leave out features. If a given feature is not provided by both frameworks, you have to either ditch it or reimplement it for the other framework. This is a big can of worms.
The whole problem stems from the fact that Java is a very inflexible language. A library provides functionality, and that's it. In JavaScript, the language itself is insanely flexible, and lets you do lots of crazy things (like writing a library, and assigning it to the $ variable). The ability to do crazy things lets developers of javascript libraries provide some really creative functionality, but it means you can't just find commonalities in libraries and write an abstraction. I think writing javascript well requires a significant change in perspective for a Java developer.
Someone wise once said "premature optimization is the root of all evil." I believe that applies in this case.
As others have expressed, you don't want to abstract for the sake of flexibility until you have an actual need for the abstraction. Otherwise you end up doing more work than necessary, and introducing unnecessary complexity before it is required. This costs money and actually makes your code more brittle.
Also, if your code is well organized and well tested, you should not be afraid of major changes. Code is always changing, and trying to anticipate and optimize for a change that may or may not come will almost always get you in more trouble than it saves you.
Acknowledgement: I should give credit to Agile programming and my practice and readings on the topic. What I've said comes directly from my understanding of Agile, and I've found it to be an extremely good razor to cut out the extra fat of my work and get lots done. Also none of what I've said is actually JavaScript specific... I'd apply those principles in any language.
There are good arguments calling this development practice - wrapping in order to switch later - into question in any language.
A good quote by Oren Eini, from his writeup on wrapping ORMs:
Trying to encapsulate to make things
easier to work with, great. Trying to
encapsulate so that you can switch
OR/Ms? Won’t work, will be costly and
painful.
This is definitely something that is done in enterprise environments.
Take for example a company that has their own custom javascript framework that is used on all of their projects. Each of the projects decide to use their own framework (jQuery, Dojo, Prototype) to add functionality to the underlying modules of the company framework. Employees that move between projects can now easily do so because their API with working the project's codebase is still the same, even though the underlying implementation could be different for each project. Abstraction is helpful in these situations.
It is overkill. Javascript is not Java and is not in any way related to Java. It is a completely different language that got J-a-v-a in the name for marketing reasons.
If you are concerned with availability of add-on libraries, then choose a framework with a large ecosystem. In an enterprise environment you will be further ahead by standardising on a vanilla off-the-shelf uncustomised web framework that you can upgrade every year or so tracking the rest of the world. And then supplement that with a SMALL in-house add-on library which you will, of course, have to maintain yourself, not to mention training any new programmers that you hire.
Since you are talking about Javascript in the client (web browser) it is more important that you limit the complexity of the things that people do with it. Don't build huge amounts of client side code, and don't make stuff that is so brittle that another programmer can't maintain it. A web framework helps you both keep the linecount down, and keep your own code reasonably simple.
It is not a question of Javascript best practice, because that would be different for server-side JS such as Rhino or node.js.
Adapter pattern is not a common solution in this case. The only example I know to use this pattern is extjs. Javascript projects are usually too small and they aren't worth the effort you would make by creating such an abstraction layer.
The common solution for this problem is that you try to use multiple frameworks together for example with jquery.noConflict.
I've done this before, and can talk a bit about the experience of writing a library/toolkit wrapper.
The plan was to move from Prototype to some other library. Dojo was the first choice, but at the time I wasn't sure whether that's the library to move everything to (and by everything I mean ~5MB of Prototype-happy JS). So coming from a world of clean interfaces, I was set to write one around Prototype and Dojo; an awesome interface that would make switching out from dojo a breeze, if that was in fact necessary.
That was a mistake that cost a lot of time and effort for a few reasons. The first one is that although two libraries can provide the same functionality, (a) their API will almost always be different, and most importantly (b) the way you program with one library will be different.
To demonstrate, let's take something as common as adding a class-name:
// Prototype
$("target").addClassName('highlighted');
// Dojo
dojo.addClass("target", "highlighted");
// jQuery
$("target").addClass("highlighted");
// MooTools
$('target').set('class', 'highlighted');
Pretty straight-forward so far. Let's complicate it a bit:
// Prototype
Element.addClassName('target', 'highlighted selected');
// Dojo
dojo.addClass("target", ["highlighted", "selected"]);
// jQuery
$("target").addClass(function() {
return 'highlighted selected';
});
// MooTools
$("target").set({
"class": "highlighted selected"
});
Now after choosing an interface for your version of the addClass you have two options: (1) code to the lowest common denominator, or (2) implement all of the non-intersecting features of the libraries.
If you go with the 1st -- you'll loose the "personality" / best qualities of each of the library. If you go with #2 -- your addClass' code will be at 4 times larger than the ones provided by any of the libraries, since for example when Dojo is included, you'll have to write the code for the function as the first param (jQuery) and the Object as the first param (MooTools).
Therefore, although it is theoretically possible, it isn't practical, but is a very nice way to understand the intricacies of the libraries out there.
I'm curious what's the view on "things that compile into javascript" e.g. GWT, Script# and WebSharper and their like. These seem to be fairly niche components aimed at allowing folks to write javascript without writing javascript.
Personally I'm comfortable writing javascript (using JQuery/Prototype/ExtJS or some other such library) and view things like GWT these as needless abstractions that may end up limiting what a developer needs to accomplish or best-case providing a very long-winded workaround. In some cases you still end up writing javascript e.g. JSNI.
Worse still if you don't know what's going on under the covers you run the risk of unintended consequences. E.g. how do you know GWT is creating closures and managing namespaces correctly?
I'm curious to hear others' opinions. Is this where web programming is headed?
Should JavaScript be avoided in favor of X? By all means!
I will start with a disclaimer: my answer is very biased as I am on the WebSharper developer team. The reason I am on this team in the first place is that I found myself a complete failure in writing pure JavaScript, and then suggested to my company that we try and write a compiler from our favorite language, F#, to JavaScript.
For me, JavaScript is the portable assembly of the web, fulfilling the same role as C does in the rest of the world. It is portable, widely used, and it will stay. But I do not want to write JavaScript, no more than I want to write assembly. The reasons that I do not want to use JavaScript as a language include:
There is no static analysis, it does not even check if functions are called with the right number of arguments. Typos bite!
There is no or a very limited concept of libraries, namespaces, modules, classes, therefore every framework invents their own (a similar situation to that of R5RS Scheme).
The tooling (code editors, debuggers, profilers) is rather poor, and most of it because of (1) and (2): JavaScript is not amenable to static analysis.
There is no or a very limited standard library.
There are many rough edges and a bias to using mutation. JavaScript is a poorly designed language even in the untyped family (I prefer Scheme).
We are trying to address all of these issues in WebSharper. For example, WebSharper in Visual Studio has code completion, even when it exposes third-party JavaScript APIs, like Ext Js. But whether we have or will succeed or fail is not really the point. The point is that it is possible, and, I would hope, very desirable to address these issues.
Worse still if you don't know what's
going on under the covers you run the
risk of unintended consequences. E.g.
how do you know GWT is creating
closures and managing namespaces
correctly?
This is just about writing the compiler the right way. WebSharper, for instance, maps F# lambdas to JavaScript lambdas in a 1-1 manner (in fact, it never introduces a lambda). I would perhaps accept your argument if you mentioned that, say, WebSharper is not yet mature and tested enough and therefore you are hesitant to trust it. But then GWT has been around for a while and should produce correct code.
The bottom line is that strongly typed languages are strictly better than untyped languages - you can easily write untyped code in them if you need to, but you have the option of using the type-checker, which is the programmer's spell-checker. Why wouldn't you? A refusal to do so sounds a bit luddite to me.
Although, I don't personally favor one style over another, I don't think that abstraction from Javascript is the only benefit that these frameworks bring to the table. Surely, in abstracting the entire language, there will be things that become impossible that were previously possible, and vice-versa. The decision to go with a framework such as GWT over writing vanilla JavaScript depends on many factors.
Making this a discussion of JavaScript vs language X is fruitless as each language has its strengths and weaknesses. Instead, do an objective cost-benefit analysis on what is to be gained or lost by going with such a framework, and that can only be done by you and not the SO community unfortunately.
The issue of not knowing what goes on under the hood applies to JavaScript just as much as it does to any translated source. How many people do you think would know exactly what is going on in jQuery when they try to do a comparison such as $("p") == $("p") and get back false as a result. This is not a hypothetical situation and there are several questions on SO regarding the same. It takes time to learn a language or framework, and given sufficient time, developers could just as well understand the compiled source of these frameworks.
Another related aspect to the above question is of trust. We continuously build higher level abstractions upon lower level abstractions, and rely on the fact that the lower level stuff is supposed to work as expected. What was the last time you dug down into the compiled binary of a C++ or Java program just to ensure that it worked correctly? We don't because we trust the compiler.
Moreover, when using such a framework, there is no shame in falling back to JavaScript using JSNI, for example. It's all about solving the problem in the best possible manner with the tools at hand. There is nothing sacred about JavaScript, or Java, or C#, or Ruby, etc. They are all tools for solving problems, and while it may be a barrier for you, it might be a real time-saver and advantageous to someone else.
As for where I think web programming is headed, there are many interesting trends that I think or rather hope will succeed such as JavaScript on the server side. It solves very real problems for me at least in that we can avoid code duplication easily in a web application. Same validations, logic, etc. can be shared on the client and server sides. It also allows for writing a simple (de)serialization mechanism so RPC or RMI communication becomes possible very easily. I mean it would be really nice to be able to write:
account.debit(200);
on the client side, instead of:
$.ajax({
url: "/account",
data: { amount: 200 },
success: function(data) {
..
}
error: function() {
..
}
});
Finally, it's great that we have all this diversity in frameworks and solutions for building web applications as the next generation of solutions can learn from the failures of each and focus on their successes to build even better, faster, and more awesome tools.
I have three big practical issues I have with websharper and other compilers that claim to avoid the pain of Javascript.
If you won’t know Javascript well you can’t understand most of the examples on the web of using the DOM/ExtJs etc., so you have to learn Javascript whatever. (For the some reason all F# programmers must be able to at least read C# or VB.NET otherwise they cannot access most information about the .net framework)
On any web project you need a few web experts that know the DOM and CSS inside out; would such a person be willing to work with F# rather than Javascript?
Being tied into the provider of the compiler, will they be about in 5 years’ time; I want full open source or the tools to be supported by Microsoft.
The 4 big positives I see with these frameworks are:
Shareing code between the server/client
Having fewer languages a programmer needs to know (javascript is a real pain as it looks like Jave/C# but is not anything like them)
The average quality of a F# programmer is a lot better than a jscript programmer.
My opinion for what it's worth is that every framework has its pros/cons and a project team should evaluate their use cases before including one. To me any framework is just a tool to be used to solve a problem, and you should pick the best one for the job.
I prefer to stick to pure JavaScript solutions myself, but that being said I can think of a few cases where GWT would be helpful.
GWT would allow a team to share code between the server/client, reducing the need to write the same code twice (JS and Java). Or if someone was porting a Java client to a web UI, they may find it easier to stick to GWT ( of course then again it may make it harder :-) ).
I know this is a gross over-simplification, because there are many other things that frameworks like GWT offer, but here is how I view it: if you like JavaScript, write JavaScript; if you don't, use GWT or Cappuccino or whatever.
The reason people use frameworks like GWT is not necessarily the abstraction that they give--you can have that with JavaScript frameworks like ExtJS--but rather the fact that they allow you to write web applications in something other than JavaScript. If I were a Java programmer who wanted to write a web application, I would use GWT because I would not have to learn a new language.
It's all preference, really. I prefer to write JavaScript, but many people don't.
We have a CMS built on Java and it has Mozilla Rhino for the server side JS. At the moment the JS code base is small but growing. Before it is too late and code has become a horrible mess I want to introduce some best practices and coding style.
Obviously the name space control is pretty important. But how about other best practices - especially for Java programmers?
Here's some tips from the front lines:
Like Java, use docblocks in Doxygen/JsDoc style for functions
Unit test. Personally like JsTestDriver, as it can be executed automatically from CI server too.
Use JSLint. It will nitpick about bad code
Consider using Google Closure Compiler. It will nitpick about code like JSLint, but it can be helpful for spotting poor doc blocks etc.
Make sure everyone on your team understands how closures work. Otherwise it'll lead to headaches
As you mention, namespaces are important especially if you want your code to work nice with other JS libraries (var myns = myns || {};)
Personally I find using a library which provides OOP helpers like classes etc. helpful. You could use prototypal inheritance but it's often a bit trickier that way.
As Douglas Crockford likes to say, JavaScript is the worlds most misunderstood programming language. Though many people don't know it, there is a right way to code in JavaScript. I have no doubt that if you let Java developers start coding before understanding how to write good JavaScript you will run into serious trouble.
The first thing to do would be to make sure everyone has read Mozilla's excellent article, A re-introduction to JavaScript (https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript). One of the biggest problems with JavaScript is that there are many ways to do most common tasks, and this article should get people on the same page. Another essential reference is Douglas Crockford's work, including JavaScript: The Good Parts.
One other thing that gets a lot of Java/C++ programmers is that JavaScript uses function scope NOT block scope. This can cause some very tricky problems. There's a great article about this issue at A List Apart called Binding in JavaScript.
To summarize the major issues talked about in the above resources, the most crucial differences to learn are
how to write object oriented code using prototypal inheritance (vs.class based inheritance)
how to use closures and lambdas
how to utilize the power of dynamic objects
how to write function-scoped code
Since you have a JS engine in Java, make it a habit to write unit tests for your JS code. Select a coding style and apply it vigorously. If possible, use tools to check that the code submits to the coding style.