Do you as a Javascript developer
consider the traditional Design
Patterns as important or less
important than they have been with
other languages / environments?.
Classical design patterns do not apply to JavaScript.
What does apply is writing modular and functional code.
You should use a mixture of Constructors and first class functions.
As a JavaScript developer I personally push towards treating JavaScript as LISP rather then Java. So try to emulate monads and high level functional style code rather then trying to emulate classical OOP code.
Please name the top three design
patterns you, as a Javascript
developer use regularly and give an
example of how they have helped in
your Javascript development.
Again design patterns do not really apply that much but below are three important constructs.
- Use of closures
- Use of first class functions
- Use of Object factories with or without
new
Please leave some kind of context for which I can show examples of these kind of techniques compared to doing the same kind of code using traditional design patterns.
Let's take a look at some of the classical Design Patterns and how to implement them in js as well as alternative patterns more suited to js itself:
Observer Pattern:
In node.js
this is simply events.EventEmitter
. In jQuery
this is $.fn.bind
&& $.fn.trigger
. In backbone
this is Backbone.Events.trigger
and Backbone.Events.bind
. This is a very common pattern used in day to day code.
I never stop and think "Hey I'm using an observer pattern here!". No this is just a low level way to pass messages around or a way to cascade change.
For example in backbone all the MVC views bind to the models onchange
event so changing the model cascades any changes automatically to the view. Yes this is a powerful pattern, but it's use is so common in event driven programming that were not realising were using it everywhere.
In the WebSocket
prototcol we have .on
which we use to bind to on("message", ...
events. Again this is very common but it's an observer on a stream rather then your classical OOP based while (byte b = Stream.ReadNextByte())
.
These are all powerful uses of the Observer pattern. But this isn't a pattern you use. This is a simple part of the language. This is just code.
Memento Pattern:
This is simply JSON. It allows you to serialize the state of an object so you can undo an action.
function SomeObject() {
var internalState;
this.toJSON = function() {
return internalState;
}
this.set = function(data) {
internalState = data;
}
this.restore = function(json) {
internalState = JSON.parse(json);
}
}
var o = new SomeObject();
o.set("foo"); // foo
var memento = JSON.stringify(o);
o.set("bar"); // bar
o.restore(memento);
In JavaScript we natively support an API for mementos. Just define a method called toJSON
on any object. When you call JSON.stringify
it will internally call .toJSON
on your object to get the real data you want to serialize to JSON.
This allows you to trivially make snapshots of your code.
Again I don't realise this a memento pattern. This is simply using the serialization tool that is JSON.
State Pattern / Strategy Pattern:
You don't need a state pattern. You have first class functions and dynamic types. Just inject functions or change properties on the fly.
Store hashtags in an array within a document.
That's the benefit of having documents: you can simply nest them. And, in this particular case, it's trivial:
{
"_id": 123,
"file": "c43a5f46-kitten.png",
"description": "My kitten :3 #kittens #cute"
"hashtags": ["kittens", "cute", "cat", "animals"]
}
(I added some "synonymous" tags, this can be done automatically by looking up some other document.)
This is the most natural solution for document-oriented database:
- Searching documents by hashtags is trivial if you just add an index, as well as inserting, updating, and deleting hashtags on random documents is also trivial
- Massive inserting, updating, and deleting is a bit tricky, because you'd probably want to split such operations in multiple "batches", but still it's manageable and not hard to implement
- Complex aggregations can be done with the standard aggregation pipeline or map-reduce
On the other hand, if you go with relational style, you'll be in a big trouble when you reinvent a SQL JOIN
within your application code. This is one of the most common anti-patterns of using MongoDB (and such). Here's a very typical pseudocode:
for (HashTag tag: mongodb.hashtags.find()) {
for (Image img: mongodb.images.find(
new Document("_id", new tag.getImageId()))) {
// ...
}
}
This is inefficient, not scalable, and you are simply reinventing a wheel. Using this, you'll probably end up with complexity of O(N*M)
because of loops within your code. If you'd choose SQL with foreign keys instead, you'd have something like O(N*log(M))
or even O(N+M)
.
There are no tables (relations) and foreign keys in MongoDB. Do not invent them, please. Use SQL instead, if you need. In fact, I highly suggest using SQL instead of MongoDB, unless your data really consists of documents.
Typical examples of documents are configurations, forms, and maybe user sessions. Those typically don't fit well into tables because of "random" structure.
Best Answer
You'd be better off using that extra bandwidth to spoon feed the map to the users as they discover it.
As you've noticed, anything client side can be easily hacked. You might think of a fancy way to encrypt the data, but you'd still have to send the decrypt keys to the browser.
For that matter, you don't really know if you're talking to a browser at all - you're just sending data over a TCP port to a computer that kind of maybe sort of looks like it might be a common web browser.