Subscribe: I Can't Believe It's Blog!
http://lazutkin.com/blog/rss201.xml
Added By: Feedage Forager Feedage Grade B rated
Language: English
Tags:
code  editor  heya unify  heya  javascript  ldquo  new  object  objects  oop  rdquo  time  unification  unify  var  web 
Rate this Feed
Rate this feedRate this feedRate this feedRate this feedRate this feed
Rate this feed 1 starRate this feed 2 starRate this feed 3 starRate this feed 4 starRate this feed 5 star

Comments (0)

Feed Details and Statistics Feed Statistics
Preview: I Can't Believe It's Blog!

Eugene's Blog





Updated: 2014-07-12T15:33:58-05:00

 



heya-unify: back to JS

2014-07-11T14:41:40-05:00

As programmers we rarely have a luxury to write a project from scratch. Usually we have to retrofit existing projects with all cool things we need. If a new component, or a library we want to use introduces new concepts that bleed outside its boundary, we have a “culture clash”, when old code is unaware about new concepts have to work with it anyhow. Sometimes the clash is so bad that we have to give up on using shiny new things, or have to significantly rework their code, which requires time and efforts we cannot afford. This situation calls for elaborate translation facilities between “old” and “new” worlds, or our new component/library should be aware of the problem, and provide necessary hooks, and utilities to adapt for existing projects. heya-unify was designed from the ground up to support such paradigm. We already saw in heya-unify: custom unification how to unify our custom objects, or modify a unification of existing objects. This post deals with results of unification by cleaning them from unification variables, so they can be used in parts, which are not aware of how those results were produced. Looking at the 1st, 2nd, 3rd, and 4th parts of the series is recommended before diving into details. Back to JavaScript Usually we use unify() to leverage unification variables, which means that our results can contain variables (essentially object references). Usually by that time all variables are bound, yet our code may not be aware of their existence. How to deal with it? A related consideration: in most cases we don’t need pure variables, but some object structures may contain them. Frequently we use patterns to parse objects, and hold parsed values in variables, and other patterns to create new objects from parsed objects. For example, we have objects like these: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var unify = require("heya-unify"), // for node variable = unify.variable, preprocess = require("heya-unify/utils/preprocess"), ref = require("heya-unify/unifiers/ref"); var input = { name: "Bob", pos: { x: 23, y: 42 // may have more properties } // may have more properties }; But we want to transform it to something like that: 1 2 3 4 5 6 var output = { x: 23, y: 42, tooltip: "Bob", original: ... // our original object }; It is easy to write an input pattern: 1 2 3 4 5 6 7 8 9 10 11 12 var self = variable(), x = variable(), y = variable(), name = variable(); var iPattern = preprocess(ref(self, { name: name, pos: { x: x, y: y } }), true); But what now? How can we assemble and pass the results, so our plain JavaScript code can deal with it, without going into details of unification artifacts, like variables? clone() We can clone an object containing variables providing that it doesn’t have circular references. While cloning all variables will be resolved and replaced with their values. This is a non-destructive operation, which keeps an original result object intact. Despite its internal knowledge of variables, clone() can be used on any type of objects. 1 2 3 4 5 6 7 8 9 10 11 12 13 var clone = require("heya-unify/utils/clone"); var oPattern = { x: x, y: y, tooltip: name, original: self }; var env = unify(iPattern, obj), result; if(env){ result = clone(oPattern, env) } As you can see our code is purely declarative and simple to understand: we described our input and output as JavaScript literals, then called unify(), then conditionally called clone(). clone() accepts three arguments: source is an object to be cloned. All bound variables will be resolved and replaced with their values. All unbound variables, unify.any, and wrapped objects will be passed as is. env is an environment to be used to resolve variables. opt is an optional configuration object, which may contain following optional properties: processObject is a procedure to handle simple objects, and unify.any. It take[...]



heya-unify: incomplete objects

2014-06-18T00:54:05-05:00

Incomplete objects allow us to concentrate on important properties of JavaScript objects ignoring the rest: we don’t need to specify every single property, and we can deal with cyclical graphs. Incomplete arrays is a complimentary feature to inspect only the first few array items. Both features are very useful for patterns, and heya-unify provides rich facilities to automate creating incomplete objects: they can be marked up explicitly on per-instance basis, recursively with a special utility, and we can specify how to deal with objects by default during unification. Looking at the 1st, 2nd, and 3rd parts of the series is recommended before diving into details. Incomplete objects From the first part of series we know that we can unify regular objects and arrays using two algorithms: “exact”, when all properties should match, and “open”, when listed properties should match, while the rest is ignored. It gives us flexibility to concentrate only on significant properties bypassing various additions, which are very common in JavaScript, and resolving potential circular references. By default all objects and arrays are assumed to be exact, but there are several ways to deal with open objects. Explicit mark up As you know already we can use a special function to mark an object as open: 1 2 3 4 5 6 7 8 9 10 var unify = require("heya-unify"); // for node var open = unify.open; var pattern = open({ position: { x: 1, y: 2 } }); open() is not recursive: only the immediate object is marked, all sub-objects will be exact unless explicitly marked. Explicit recursive mark up Frequently we want all objects of our pattern to be open. Marking them up one by one gets old pretty quick. Precisely for such case there is a utility that handles it: 1 2 3 4 5 6 7 8 9 10 var preprocess = require("heya-unify/utils/preprocess"); var pattern = { position: { x: 1, y: 2 } }; pattern = preprocess(pattern, true, false); preprocess() accepts four arguments: source is an object to be processed. nonExactObject is a flag. If it is truthy, all objects excluding arrays, standard dates, regular expressions, and unification variables, are marked as open. Otherwise they are unchanged. nonExactArrays is a flag. If it is truthy, all arrays are marked as open. Otherwise they are unchanged. opt is an optional configuration object. It can be used to specify special treatment of custom objects. Following optional properties can be specified: context is an arbitrary object, which will be passed to all other functions. It will be pre-populated with following properties: stackOut is an array used as stack to push converted objects. Ultimately all object processing procedures should push results there. wrapArray(val) is a function, which makes arrays open (see “Internal mechanics” below). By default it has a falsy value, and not used. wrapObject(val) is a function, which makes simple objects open (see “Internal mechanics” below). By default it has a falsy value, and not used. processObject(val, context) is called for every simple object. processOther(val, context) is called for every non-object as defined by typeof, or null. registry is an array similar to unify.registry: All even items are assumed to be constructor functions. Objects are compared against them with instanceof. Corresponding odd items are transformation procedures, which the same signature as processObject() above. filters is an array of functions. Each function takes the same parameters as processObject() above, and returns a truthy value, if it can handle an object, or a falsy value otherwise. It is not necessary to specify registry and filters directly in opt. Their default values are exposed as properties on preprocess(), and can be modified in place for lasting changes. preprocess() returns a clone of source leaving source unmodified. Let’s exclude instances of Person from preprocessing as an example on customization: 1 2 3 4[...]



heya-unify: custom unification

2014-06-10T00:24:00-05:00

Custom unification in heya-unify allows us to deal with our specific objects in JavaScript, create unification helpers, and even custom logical conditions. It is there to bridge unification with our existing projects. Looking at the 1st part and the 2nd part of the series is recommended before diving into details. Custom unification Unification makes comparing simple objects a cinch no matter how complex they are, and we can easily apply it to JSON-like trees as is. Additionally heya-unify “knows” how to unify other common JavaScript objects: dates, and regular expressions. Yet in Real Life™ we are faced with complications like that: Our objects contain secondary sub-objects, which are there for purely technical reasons, e.g., to cache related objects, and they should be ignored. While objects have many properties only a few of them are useful for identity checks, e.g., a Person object can be compared by its social security number, or its equivalent, rather than name components, date of birth, and other fields. When building a binary tree we may include a reference to a parent object to simplify our algorithms making the whole structure circular (a parent refers to children too), which is not something we want. While JSON-like structures are a huge chunk of data we process (they come from databases, and web services), there are many legitimate scenarios, when we cannot use a naive unification. How to deal with it? heya-unify has a number of provisions to do it safely and efficiently. Unifier: the base class One way to do it is to make our objects unification-aware. In order to do that we should base them on a well-known base Unifier: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var unify = require("heya-unify"), // for node Unifier = unify.Unifier, variable = unify.variable; // let's create a unification-aware object function Person(name, dob, tin){ Unifier.call(this); // calling our base constructor first this.name = name; this.dob = dob; // date of birth this.tin = tin; // tax identification number } // register our base using single inheritance Person.prototype = Object.create(Unifier); // because our government assigns unique TINs to individuals // with similar names and even the same date of birth, // we can use it for identification purposes disregarding the rest // our custom unification function Person.prototype.unify = function(val, ls, rs, env){ return val instanceof Person && this.tin === val.tin; }; Or, if we use dcl, it is even simpler: 1 2 3 4 5 6 7 8 9 10 11 12 var dcl = require("dcl"); var Person = dcl(Unifier, { constructor: function(name, dob, tin){ this.name = name; this.dob = dob; // date of birth this.tin = tin; // tax identification number }, unify: function(val, ls, rs, env){ return val instanceof Person && this.tin === val.tin; } }); Now we can use Person for unification without worrying, if we have more fields, or even circular references to parents, spouses, children, or whatever data model we have. One good question is: what kind of object is TIN? Typically it is a string of numbers or symbols, but in some countries it can have its own structure, which can be represented by its own object. How to deal with it? In the above example we assumed that it is a primitive value, likely a string. What if it is not? Actually this part is super easy. The secret is to delegate unification down the line: 1 2 3 4 5 6 7 8 9 // our new custom unification function Person.prototype.unify = function(val, ls, rs, env){ if(val instanceof Person){ ls.push(this.tin); rs.push(val.tin); return true; } return false; }; Now let’s discuss the unification method. It has following arguments: val is an object, we are asked to unify with. It is up to us to check if it is a suitable target, and how to do the unification. ls and rs are two arrays, which are used for pair-wise unific[...]



When to unify in JS

2014-06-05T18:10:33-05:00

Unification for JS introduced heya-unify — a practical mini library to leverage unification in JavaScript. This post explains when it makes sense to use unification, and gives practical examples of how to use it. When to unify? Below is my laundry list for unification. As soon as I see a project, which deals with items on the list, I investigate if it makes sense to use heya-unify. Matching and transforming An obvious sweet spot is when we need to inspect deep objects saving sub-objects for future use, and possibly matching some sub-objects. It is worth noting that even complex arbitrary graphs with loops are a fair game. The same goes for sub-objects: it is equally easy to compare and save complex sub-trees as well as primitive objects. Matching against circular structures is possible, but may require utilizing some simple techniques like variables, open objects, or custom unifiers, which are explained in details later. NoSQL Unification is a natural fit for document-based NoSQL databases. Imagine that we have a collection of so-called sparse or incomplete documents. If we use a traditional SQL database for that by mapping our documents to an extended collection of fields, we will have a database with an extraordinary number of nulls, and bad performance. Even a normalization, if it is possible at all, is unlikely to cure the problem. The situation is even worse, when we don’t have a fixed schema for our data. For example, it should be discovered first by collecting representative data samples. Sometimes we know what we are dealing with, but lack statistics to properly normalize/denormalize our tables, and allocate indicies properly. This situation calls for NoSQL, and unification can help dealing with such dynamic data. Web services While NoSQL is an important use case, dealing with web services is even more important. Usually web services are designed to provide generic responses to cover a wide range of possible clients. In most cases they provide more information than we need. Typically we validate their responses, and extract only relevant pieces ignoring the rest. Unification doesn’t care if our data come as JSON or XML (both are popular choices for web services), because it deals with already instantiated JavaScript structures making it data format-agnostic. RAD Unification is a good RAD tool. Instead of writing imperatively a bunch of if statements, and allocating technical variables to remember sub-objects, we just specify a shape we need declaratively. The result is easy to write, to understand, and to modify, if a need arises. Example: trivial data processing Let’s assume that we deal with personnel records, and we want to plot annual salary sorted from lowest to highest to see its distribution. For simplicity sake, each position has a base salary, which we can use. If an employee negotiated a custom compensation package, their salary is recorded directly in a personnel record overriding the base salary. Let’s sketch our objects trying to keep the example as minimal as possible: 1 2 3 4 5 6 7 8 9 10 11 var position = { title: "Unit manager", // position's title baseSalary: 100000 // base compensation // more information }; var employee = { name: "Jane Doe", // employee's name position: position, // employee's position salary: 101000 // optional salary information // more information }; employee is a model for personnel records. It refers to position. In fact, many records can refer to the same position object, and that object may have back links to employees in that position. Our fictional charting package requires data as an array of following data points: 1 2 3 4 var dataPoint = { value: 100000, // a numeric value to plot tooltip: "Jane Doe" // name to identify this data point }; First let&[...]



Unification for JS

2014-05-18T16:39:16-05:00

Unification is a very interesting programming tool. Originated from logical programming (its the foundation of Prolog) and used in functional programming (e.g., Haskell) it helps to compare objects for equality, identify known patterns, and reassemble results differently. Wikipedia gives a somewhat complex definition of unification, but many people see it as an extended equivalence comparison, a pattern matching tool, and some even find parallels with XPath queries, CSS, and even jQuery, all operating on regular objects. See it for yourself. While JavaScript provides a notion of equality, it lacks structural matching. Fortunately it is easy to write one ourselves. It is in the same category as cloning and copying objects. Unification is not a new concept. There are several open source libraries available, I will talk about heya-unify, which implements a symmetric first-order unification algorithm custom-tailored for JavaScript. I authored this module some time ago, and used successfully in my projects. In order to try examples with node install it with npm: 1 npm install heya-unify It can be used in browsers with an AMD loader/builder like require without modifications. The project itself is available on GitHub: heya-unify. Structural matching The problem: JavaScript doesn’t readily provide tools to match objects. For example, these two simple objects are not equal: 1 2 3 var a = [42], b = [42]; a == b; // false a === b; // false The same goes for {}: 1 2 3 var c = {luck: 7}, d = {luck: 7}; c == d; // false c === d; // false Why? Because internally JavaScript doesn’t try to match structures of those objects, but opts to compare their internal memory addresses. The latter is easier and faster, but frequently is not what required. We can think of unification as a way to compare those objects structurally down to primitive types: 1 2 3 4 var unify = require("heya-unify"); // for node unify(a, b); // truthy unify(c, d); // truthy unify() accepts two mandatory arguments (objects to unify, can be passed in any order), and an optional environment argument (more on that later). Usually unification objects are JSON-like, but custom objects can be used as well. For example, out of box unify() can deal with arrays, dates, and regular expressions. When unify() checks for structural equivalence, it pays attention to objects being exact. It means that objects should have the same number of enumerable properties with the same names, and equivalent values. This behavior can be controlled by programmer (discussed below). While comparing two data structures for exactness is useful, it is rarely needed in real programs. Yet there is one super-important use case for such unification: unit tests. If our function should produce a complex data structure, and we know the result, or its shape, we can unify them to see, if we got what was expected. That’s why heya-unify is extensively used in heya-unit, which will be a subject of another blog post. Variables Sometimes we don’t know an exact value of a certain component, and want to figure it out. In this case we can supply a variable instead of an actual value. During matching, this variable will be assigned a value, which we can query back later. Our next example will “unpack” 2D coordinates from a JSON-like object: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var variable = unify.variable; // to declutter our example var x = variable(), y = variable(); var pattern = { position: { x: x, // instead of actual values, we specify variables y: y // to receive those values } }; var env = unify(pattern, {position: {x: 2, y: 3}}); if(env){ console.log("position:", x.get(env), y.get(env)); // it will print: "position: 2 3" } Note how natural and simple it was to define a pattern. This simple example shows important points: unify() ret[...]



Serve files with nginx conditionally

2014-02-23T17:52:58-06:00

Time and again working on big web applications we customize files based on user’s platform, and their preferences. We can send different files to legacy browsers, different CSS and JS to mobile browsers depending on their form factor, different images to accomodate bandwidth requirements, and so on. This post was prompted by my desire to serve sprites produced by grunt-tight-sprite as WebP images to WebP-capable browsers falling back to “classic” image formats for the rest using nginx. While it is hardly a new topic, I was not satisfied with existing solutions, which all used if and rewrite, instead of simpler methods. Obviously the core solution can be used to serve almost any file conditionally, not only images, but all examples will be about WebP. The problem at hand One common technique to conserve connections and bandwidth, especially on mobile platforms, is to use sprites instead of individual images. See Sprites by CSS on Wikipedia for more details. While the upcoming HTTP 2.0 will reduce the need for sprites by using one connection to request images (and other files) asynchronously, the technique will still be valid due to a possible bandwidth gain by compressing several images together. There are several tools to incorporate sprites in web developer’s workflow. I work on one of them: grunt-tight-sprite (see its wiki for more details), and I know the problem first-hand. Generally sprites (or sprite sheets) are relatively big images, so every bit of extra compression helps. That’s why we crush resulting sprites with zopflipng or with jpegtran. We take our images to the limit. But can we do better? Enter WebP. About WebP WebP is “a new image format that provides lossless and lossy compression for images on the web.” It improves on lossless PNG and lossy JPEG without compromizing on visual quality, and implements new features, like lossy alpha channel. WebP-capable browsers advertise themselves by including "image/webp" string in an HTTP Accept header. Right now Chrome and Opera support WebP on desktop and Android platforms (see Can I use WebP image format? for more details). Firefox may support WebP in future versions. Given the popularity of Chrome, and gazillions of Android devices on the market, it makes perfect sense to support WebP in addition to legacy formats. Our goal Now we can sketch the final goal: Let’s clone our images and produce WebP version of them. If user’s browser supports WebP, we will send them a WebP version. If we don’t have a WebP version for some reason, we will send a legacy version. All other users will receive a PNG or JPEG image. Obviously, to reduce expenses on dynamic generation of images, we will convert them to WebP statically. grunt-tight-sprite has a recipe for that. Now we have to serve files making decisions. Let’s remove from the table web services, and other high-level solutions — they are too heavy for our needs. Let’s leverage our web server: both Apache and nginx can do it using “native” tools. Existing solutions Hitting the web we will find a lot of good battle-tested recipes for nginx. The problem is that all of them “smell” like Apache + C: they use if and rewrite to achive their goal. One of the best articles on this topic is Deploying WebP via Accept Content Negotiation (code repository) by Ilya Grigorik of Google — it is small, concise, practical. Yet again, it relies on if and rewrite. What’s wrong with if and rewrite? According to nginx Wiki “if is evil” (yes, this is how it is phrased in Wiki). “Directive if has problems when used in location context, in some cases it doesn’t do what you expect but something completely different instead. In some cases it even segfaults. It’s generally a good idea to avoid it if possible.” It is frequently mis[...]



CG: code generation in JavaScript

2013-07-14T00:41:00-05:00

ClubAjax invited me to speak about technologies behind Heya, specifically about code generative solutions behind heya-pipe. Pipes are built on a firm foundation of functional programming (FP), and it allows us to use a wide range of technologies to optimize their performance including generating code on the fly (code generation AKA CG).

As soon as we are talking about CG, the first question to ask is: “How to debug such code?”. Heya provides answers for that too. But no spoilers.

Direct link: Practical pairing of generative programming with functional programming.

(object) (embed)

View more presentations from Eugene Lazutkin.




Switched to Octopress

2013-07-14T00:19:00-05:00

After 8 years I decided to switch to Octopress. Being a server-less framework, it allows my web site to scale better, and, the most important thing for me, reduces expences on administring an active server (less active components to update). An additional bonus is that it reduces requirements for a web site host, which allows me to be more flexible when selecting a hosting company.

All old links are supposed to work as they used to be redirecting to new URLs. Please let me know, if something doesn’t work for you.




Slides: optimization of modern web applications

2012-08-13T07:54:08-05:00

I spoke at ClubAjax about optimization of modern web applications. Usually I speak about theoretical matters, but this time I decided to go practical. This is a huge topic and it was blogged/debated/presented to death, including my Improving performance…. Yet I decided to add to it after realizing that many things have changed in last years, including how we build web applications. I concentrated on technical aspects completely bypassing all other areas (e.g., a psychological angle).

Fair warning: these slides were my talking points. Feel free to ask me, if you found some slides lacking or even puzzling, or can improve on mentioned techniques.

Direct link: Optimization of modern web applications.

(object) (embed)

View more presentations from Eugene Lazutkin.




More on 0ms timeouts

2012-07-28T07:15:38-05:00

Once I wrote a blog post On JavaScript, EDP, and 0ms timeouts, which discussed a "smart" trend to pepper code with timeouts of … 0ms: setTimeout(f, 0). Authors of those "programming pearls" genuinely believed that this code reschedules a function call to the next available time slice after the code that set the timer was executed without introduction of a delay (after all it is 0ms!). In reality a typical delay was 10-20ms. With new generation of browsers it starts with 4ms and jumps to 1000ms for non-current/hidden tabs. Obviously there are legitimate uses of timeouts: polling a server with some interval, throttling events, animation. The 0ms trick is not among them. And the animation is better served by Timing control for script-based animations. This is the "0ms timeout" in all its glory: 1 2 3 4 5 6 7 8 function f(){ // do something } // ... // here it goes: setTimeout(f, 0); There are two problems with this approach: It makes debugging such code a nightmare, especially when you have several timers in-flight, and/or this particular timer invocation can be called from different places. The problem is that the history of such call is completely lost – all you see in debugger is a short call stack, which starts with setTimeout. It would be almost impossible to unravel why globals and/or closure (common ways to set up data for a timer callback function) are set this way. While "0" looks assuring, it is not 0ms. It does involves a timeout no matter what. Here is a program from my previous article to try it for yourself: test chained timeouts (try it with current, and non-current tabs). Current breed of browsers restricts timer-based polling to 4ms for current tabs, which is an improvement on 10-20ms in previous versions. But if your user switches to another tab for a moment, timers will be executed once per second – 1000ms delay. This is probably fine for an animation, and for server polling – why bother updating something, if user cannot see it at the moment. It saves CPU and bandwidth making the current tab more responsive. Even a delay of timer callback doesn’t sound too bad. Who cares? The real problem is in accidental or purposeful chaining of such callbacks. Working on a real application, which used a signal library to send light-weight low-level events between program pieces, I found that cascading signals (a handler of one signal sent another signal) created chains up to ~10 signals one after another. The total delay was ~100-200ms, which was noticeable by end users. The problem was that nobody could explain those delays. For end users those delays looked completely illogical: no major calculations, no I/O with server, yet you can clearly see how data is being updated piece by piece in front of their eyes. The new policy of throttling timers of non-current tabs to 1FPS makes the 0ms timeout technique unsustainable in a general case. Some examples: If we accumulated a few heavy callbacks before user switched a tab, on her return we will have a workload of (potentially obsolete) tasks to perform. It would be perceived by an end user as a delay before things got normal again. If we produce temporarily more signals than we process (it happens all the time), and user switched, we can clog our timer queue with (potentially unnecessary) updates. Again, it means a delay. Users hate delays, especially when they are not expected logically. If our program involves timers to do time-specific tasks, they can interfere with "0ms timeouts". Frequently this interaction is unpredictable. For example, we may assume that all "0ms timeouts" are fast and executed way before our next time interval. Now this assumption is wrong, which can lead to incorrect results at the very least.[...]



OOP in JS slides

2012-07-17T18:02:55-05:00

Finally: my open source JavaScript project DCL is built on ideas described in this article. Available for node and modern browsers, it implements OOP with mixins and AOP at "class" and object level. Read documentation and background articles on www.dcljs.org, clone its code on github.com/uhop/dcl, and follow @dcl_js.

Once again I was invited in ClubAjax to speak about JavaScript. This time I did a presentation based in part on my previous blog post OOP and JS. Slides and talk revisit OOP, mixins, AOP, chaining, and other related techniques I discussed in my blog. Of course, OOP deficiencies were discussed at length too. I suggest to look at slides and read the blog post – it will give you a better picture.

I feel that such basic programming techniques are essential for everyday work. Done right they provide a solid foundation for our projects. That’s why I intend to build the next generation of OOP, AOP, FP libraries building on existing proven technologies.

Direct link: OOP in JS.

(object) (embed)

View more presentations from Eugene Lazutkin.




OOP and JS

2012-01-18T10:26:59-06:00

Finally: my open source JavaScript project DCL is built on ideas described in this article. Available for node and modern browsers, it implements OOP with mixins and AOP at "class" and object level. Read documentation and background articles on www.dcljs.org, clone its code on github.com/uhop/dcl, and follow @dcl_js. Almost any Java programmer, who starts to study JS groking its OOP facilities and a dynamic nature of JS, thinks that they can be greatly improved and starts its own OOP library/helpers. Majority of them left forgotten when their authors learn more and more details and patterns of JS, yet some grow to fruition and being marketed. This article is dedicated to such people. The goal of this article is to go over common OOP techniques suitable for JS, their pitfalls, problems, and trade-offs. Warning: this article is not for beginners. You have to be familiar with OOP at least in one language, and have good understanding of builtin OOP in JS. Why OOP? People who heard me talk about programming techniques, or read my articles and slides, know that I think that OOP is frequently overused and abused, and we are missing good practical alternatives. Previous blog posts on this topic: Functional fun with JS in Dojo Using recursion combinators in JavaScript AOP aspect of JavaScript in Dojo On JavaScript, EDP, and 0ms timeouts Why OOP? I think this is a very important tool when used correctly, which should be done right. If somebody decided to do it, make sure that you don’t cripple it in some way. Builtin OOP in JS I am not going into details of a prototypal inheritance implemented in JS. If you want a refresher, I suggest to read excellent articles by Douglas Crockford: Classical inheritance in JS Prototypal inheritance in JS Single inheritance OOP: what is available? First of all, OOP is a set of concepts, and any existing language implements some subset of it. It doesn’t make sense to declare one language “purer” then another, or enshrine one particular implementation as canonical. The foundation of OOP is an object (not class, not constructor, not any other thing), which encapsulates state, and defines methods to deal with an object. Yes, OOP is a branch of the imperative programming. It provides a neat way to partition/structure your program state into manageable pieces thus reducing overall complexity. It has nothing to do with pure functional programming or any other stateless techniques. Other things, which are usually associated with OOP, like classes, constructors, interfaces, and so on, are optional. Some techniques work best when applied statically, yet absolutely unpractical in dynamic languages for performance reasons. Good example would be interfaces. In many cases simple duck-typing will do. Let’s start with single inheritance and work our way up. Classes and factories One of the major principle of any programming is eliminating repetitive tasks. We would not go long without loops. Likewise we wouldn’t go long, if we produce each and every object by hand. That’s why we classify objects (in a philosophical sense) and provide simple ways to mass-produce them according to their classes/categories. Compiled languages usually rely on “classes”, which serve as “recipes” for a language to verify and produce new objects. The other frequently used alternative is to provide special entities called “factories”, which can produce new objects. Factories can be objects, or functions. Essentially this is what JS uses — a function called “constructor”. Calling this function repeatedly we can mass-produce similar objects. Object invariants One important rule/convention is to observe proper invariants on an object. In most cases it is a validity requireme[...]



Using Dojo Rich Editor with Django's Admin

2011-03-13T14:39:22-05:00

Many years ago I decided to replace plain text areas in Django’s Admin with rich text editor, so I can edit HTML on my blog using WYSIWYG. Six (yes, 6) years ago I looked around and selected TinyMCE. Over time it turned out that I was forced to upgrade TinyMCE and the link script I had because new browsers continue breaking my rich editor editing. Finally it stopped working again in all modern browsers, and I decided that enough is enough. It is time to replace it. This time I settled on Dojo’s Rich Editor hosted on Google CDN — simple, functional, less work to set up. Selecting features Adding Dojo’s editor to Django’s Admin was very simple. The most complex part turned out to be selecting what cool features I want to use. See, dijit.Editor is fully pluggable, and it is easy to extend with your own plugins. Some day I’ll do just that, but for now let’s use what’s available. dijit.Editor comes with two sets of plugins. Let’s go over them and select plugins we want to use. The first set is in Dijit’s editor plugin repository: FullScreen: allows editor to take over the whole page. Toggleable. This is one of the most important plugins for me: I hate to edit text in an itsy-bitsy window, yet if I make an editor window big, it becomes hard to see other parts of the document with all scrolling around. Ideally I want it small, when I look at my document with a rich text screen, but becoming big when I want to edit it. Hence FullScreen. ViewSource: toggles between rich editor and a simple text editor to edit underlying HTML. I am an HTML professional and time to time I need to edit my HTML manually, so this plugin is extremely important for me too. TextColor: allows to select foreground and background color. Need it. FontChoice: formatting paragraphs, selecting font families and sizes. Need it too. LinkDialog: adding links and images. Need it. Print (printing), NewPage (clearing editor), and ToggleDir (switching between LTR and RTL languages) — I have no need for them. Skip. The second set of plugins comes from DojoX’ editor plugin repository: PrettyPrint: formats HTML in a readable way. Well, I’ll be manually editing HTML, so I obviously want it. ShowBlockNodes: shows what elements are used for formatting in WYSIWYG mode. Obviously I can use ViewSource for that, but this plugin sounds like fun, let’s add it. InsertEntity: allows selecting HTML entities visually. I love it! I frequently use "—" (em-dash), arrows like "⇒", and so on, yet rarely remember abbreviations. It is a keeper. NormalizaIndentOutdent: some enhancements on indenting/outdenting to avoid browser-specific differences. Sounds useful. FindReplace: finds and/or replaces text. Obviously I want this functionality in my editor. CollapsibleToolbar: hide/show editor’s toolbar to make more space for edited text. Sounds cool, I like it. Blockquote: it sounds exactly like what it does. I use block quotes, so we’ll add this plugin as well. InsertAnchor: inserts an anchor for future references. Useful. TextColor: again? Yep. But it is much cooler than its counterpart from Dijit. We’ll replace that plugin with this one. AutoUrlLink: converts URLs into proper tags. Need it. PasteFromWord: clean up dirty HTML using predefined filters. Sometimes I use Open Office or Google Docs to prepare my posts ⇒ I think this functionality will come handy. ToolbarLineBreak: allows to insert line breaks into editor’s toolbar. We are going to have quite a few plugins, so we will need this plugin for sure. TablePlugins (table operations), PageBreak (inserting
), Preview (show edited content in a separate wind[...]



What happened to Dojo in 2008?

2010-03-15T17:56:16-05:00

What happened to Dojo in 2008? This question was asked on StackOverflow. This is my personal take on the matter: on Dojo, jQuery, history, mistakes, marketing, social vs. technical, and communities.




Exciting JavaScript Part II

2010-03-04T08:48:03-06:00

This month I continued my presentation at ClubAJAX. Last time I did a survey of what is available in JavaScript, and concentrated on object-oriented (OOP) and aspect-oriented (AOP) techniques. This time I continued the survey, and talked about functional programming (FP), and domain-specific languages (DSL). And as promised I touched the code generation facilities too.

I suggest to read the first part before.

Enjoy!

Direct link: Exciting JavaScript – Part II.

(object) (embed)

View more presentations from Eugene Lazutkin.




RAD CRUD

2010-02-10T11:40:25-06:00

Today at dojo.connect I did a presentation “RAD CRUD”: rapid development of form-based applications. It continues my other presentation “CRUD with Dojo”, but it is more in depth, targets Dojo developers, and contains some advanced material.

Direct link: RAD CRUD.

(object) (embed)

View more presentations from Eugene Lazutkin.




Exciting JavaScript Part I

2010-02-05T16:34:26-06:00

I was asked to talk about advanced JavaScript techniques at the last monthly meeting of ClubAJAX — monthly get-together of Dallas-area JavaScript programmers. Instead I ended up talking about leveraging cool JavaScript features to implement well-known programming techniques and paradigms: OOP, AOP, FP, and so on.

Unfortunately I couldn’t finish in time, so I did a tour of some language features, and talked about OOP and AOP. The rest (I plan to do FP, code generation, and DSL) will be covered later.

So I split my slides into two parts and today I publish the first part. In a month or so, when I deliver the second part, I’ll publish the rest.

Enjoy!

Direct link: Exciting JavaScript – Part I.

(object) (embed)

View more presentations from Eugene Lazutkin.

Update: I published the second part.




Dojo Charting demo: tribute to Highcharts

2009-12-07T23:48:56-06:00

Wolfram Kriesing asked:

Somehow I have the feeling that you can bend dojox’s charting module to look and feel like http://highcharts.com/ — will be for free.

Yes, it is relatively simple. To prove a point I wrote a quick-and-dirty demo available here: Tribute to Highcharts. Obviously not everything matches 100%. Go and judge for yourself.

Update: related post on dojo-dev mailing list, which explains some details of the demo.




CRUD with Dojo

2009-12-01T18:02:11-06:00

My presentation at ClubAJAX got off to a rocky start: I was let in the building 40 minutes after I was supposed to start the presentation. Everybody waited patiently. Thank you guys! As promised I publish slides along with relevant links (I had to skip most of planned demos).

Here is my presentation on SlideShare: CRUD with Dojo. The original presentation can be seen on Google Docs: CRUD with Dojo.

(object) (embed)

The relevant links from the presentation (all demo links point to a test server ⇒ slow):

My thanks go to the Dijit team for their titanic work: Bill Keese, Doug Hays, Becky Gibson. You rock, guys!




Adding django-shorturls

2009-08-06T11:52:34-05:00

Time to time I sync my blog software to the Django trunk and introduce small enhancements. Some of them visible to my readers, some of them are just for me. This time after reading Simon Willison’s post on rev=canonical I decided to add short URLs to my blog as well. This is a convention to provide custom short URLs managing the mapping on your own web site. In my opinion the idea is very cool. To be completely honest: while I like the idea I am not completely sold on its implementation. For example Mark Nottingham advocates a different way to provide the same information: rel=shorturl (via Simon’s post), and it sounds more logical to me. Oh, well. The first approach is easy to try: Simon coded it for Django, and Jacob Kaplan-Moss even created a full-fledged Django application out of it available both on github and on pypi — with this kind of availability I had no excuse not to try it. And rev=canonical can be used together with rel=shorturl, if I want to add it later, using the same universal django-shorturls application. So after buying lzt.me domain I armed myself with Simon’s article and Jacob’s git repository, and set to add it to my blog. And while everything about django-shorturls is super-simple I managed to hit the brick wall repeatedly in all possible ways (don’t judge me too harsh — I decided to do it at night not thinking clearly). Below you will find a list of gotchas for myself and others: While the application is called “django-shorturls”, when it is installed it is available as “shorturls”. Simple enough. While the application is available as “shorturls”, its template tag library is called “shorturl” (no s at the end). Somehow my fingers typed “shorturls” in all templates — probably my tired brain expected that the major piece of functionality is called exactly as the application itself. It looks like Jacob was confused like me and typed it both ways in examples of the readme file. The main tag is called “shorturl” logically enough. Probably that’s what gave the name for the template library. After coding everything up (literally 5 minutes + stupid gotchas above) I’ve noticed that in some places I am getting nothing instead of an expected URL value. I figured that something is wrong and Django famously silenced errors in templates. After frantic attempts to debug the problem I’ve noticed that I misspelled a name of my model in SHORTEN_MODELS settings. The stupid typo led to exceptions in the template tag, which was silenced, and no other diagnostics were given. Now everything works as expected per Jacob’s readme, yet no cigar — my blog generates URLs like this: http://lzt.me/dBh, but it doesn’t process them. Instead it expects URLs like this: /short/dBh. WTF? There is nothing about it in the readme. But Jacob starts it by referencing Simon’s article, and if you read it to the end you would know that it requires a little help from a web server: a URL rewriting. Simon does it with nginx. I love nginx! In fact I use it to drive my web site. Finally I got lucky and can use his recipe directly! I copied Simon’s code and… it doesn’t work. The close inspection found the problem: django-shorturls expects incoming short URLs to be anchored at /short/, but Simon’s code rewrites to /shorter/. An easy fix when you know the problem. While I am embarrassed to have so many mishaps with a simple application, I [...]