In: Categories » » AJAX » Understanding the Ramifications of Duck Typed Code
Understanding the Ramifications of Duck Typed Code
Problem You want to understand where to best use duck typing and the issues you should be aware of when using it. Theory There is a difference between a value type and a reference type in JavaScript. Even for a reference type, there is a difference between defining the reference as a value or a pure reference. But should you even care about the difference? Is it something that you need to be aware of? It is when you are trying to do something specific. JavaScript is a unique language in that it has duck type, latent type, and prototype characteristics. To create a type in JavaScript, you can define the type via a prototype definition, or you can define the methods and properties by assigning a class instance. In general, you have the ability to dynamically wire together types at runtime. There are two ways to implement duck typing: value types and reference types. You need to be aware of both types, although in this article Imostly use value-type duck typing. I am not saying one is better than the other just that each has advantages and disadvantages. Developers tend to choose one over the other based on their programming habits. For example, I prefer value duck typing because I tend to serialize objects for later use. Solution Let’s go through an example of duck typing using reference values. Consider the following code, which is used to create a function without parameters that contains a state.
Source: /client/ajaxrestrecipes/javascript/valuevsreferencetypes.js
function CallMeReference(toCall, value) {
return function() {
toCall(value);
}
}
In the preceding code, the CallMeReference function has two parameters: toCall, which is a function, and value, which is the state used to call the function toCall. The idea behind CallMeReference is to create a function that has no parameters, but is called using some state defined earlier. The following code could be used to execute an example:
var func = CallMeReference(
function( param) { info( "param is (" + param + ")"); }, "hello world");
func();
In this example, the func variable is used to generate an encapsulated “hello world” message. The func variable can be called repeatedly, and the same message is generated. The variable could be assigned to other variables and the same message would be generated. Because we are programmers, we will create functions that follow the Builder pattern and precreate functions with certain states. The following two functions implement the Builder pattern:
function Version1Reference() {
return CallMeReference( function( param) { info( "Ver 1 is (" + param + ")"); },➥
"hello world");
}
function Version2Reference() {
return CallMeReference( function( param) { info( "Ver 2 is (" + param + ")"); },➥
"hello world");
}
The Version1Reference and Version2Reference functions generate functions with slight differences. The resulting generated functions can be assigned to variables and then called as in the previous example. Up to this point, everything that I have shown is something you could do using traditional programming languages such as C#, Java, and C++. Here, however, we are using JavaScript, which implements duck typing and prototype-based features, which means that if a function is assigned to a variable, we don’t know how that assignment happened. This need to know who did what assignment does not matter in C++, C#, or Java, because the programmer defined the order and layout of the types ahead of time, and during runtime that order cannot be changed. In JavaScript, that order is not defined ahead of time it is defined at runtime. For example, the following code is possible:
if( flag) {
func = Version1Reference();
}
else {
func = Version2Reference();
}
When func has been assigned, you don’t know if it was assigned using the code from Version1Reference or from Version2Reference. When the assigned code is executed, you can logically determine from the behavior if the Version1Reference or Version2Reference function was used. The reason I say that you don’t know which code was assigned is because when you serialize the variable func, the following code is generated:
function () { toCall(value); }
The generated code tells you that the toCall and value variables have been assigned, but you don’t know to what. This can become problematic if you are trying to serialize an object that references the generated function. If you serialize the function and attempt to execute the function, an error would be generated because the toCall and value variables would not be defined. You can serialize the state of the data members, but serializing the methods causes state to be lost.For example, imagine you are writing a mortgage application, and you are currently creating a client.
The client has a certain age, address, and profile. In a traditional programming environment, you would associate the state with an object each and every time the state is loaded. This means each time the state is loaded, you have to execute various Builder pattern implementations to create the appropriate object type. Using JavaScript, this is not necessary because the state of the object, including methods, could be serialized. This makes it possible to serialize a complete object, store it into a database, or execute it in another context. Dynamic functions need to use value types, which means CallMeReference has to be modified as follows:
function CallMeValue( toCall, value) {
return eval( "function() { var func = " +➥
toCall.toString() + "; func( '" + value.toString() + "'); } ");
}
The CallMeValue function is like CallMeReference, except that it serializes the function and value to string buffers that are concatenated and executed. The result of the execution is a function that when serialized generates the following buffer:
function () { var func = (function (param) {info("param is (" + param + ")");});➥
func("hello world"); }
The serialized function behaves exactly like the function created in CallMeReference, but the value function can be serialized and executed on another computer or in another context. When writing code that dynamically wires together code, you need to think about whether to use reference or value programming techniques. When writing such code, consider the following rules of thumb:
• Reference duck types should be considered as transient types that live only for the extent of the JavaScript execution (e.g., an HTML page).
• Reference duck types are created using the Builder pattern.
• Once created, reference duck types have a slight performance advantage, as they do not need the overhead of running the eval statement in the Builder pattern implementation.
• Reference duck types can share instances with multiple object instances because you are assigning references.
• Value duck types should be considered as long-term serializable objects where the state and code can be serialized.
• Value duck types are created using the Builder pattern.
• Value duck types are slightly slower than reference duck types because the code is the result of serializing, building a buffer, and then evaluating the buffer.
• Value duck types do not have the side effect of having functions behave irregularly because of assigned object instances. Each call to a value duck type Builder pattern results in a clean-slate approach, where the variables are assigned the state given to the Builder pattern.
legal notice
Our website is not responsible for the information contained by this article. Web-articles is a free articles resource.
Suggestion: If you need fresh, daily updated content for your website, feel free to use our service. Click here for more information.
Useful tools and features
If you like this article (tutorial), please link to it from your web page using the information above.
related articles
Coding the Contract Using Test-Driven Development Techniques Coding the contract using agile and test-driven development techniques requires writing a number of tests and implementing aMock URL layer. Problem You want to code the contract using these development techniques. Solution To demonstrate, let’s define a use case, implement the use case as a contract, write a test case(s) to implement the contract, implement the contract in the Mock URL, and finally...
2. Testing the Client Side Logic
Problem You want to effectively test your application’s client-side logic. Theory Testing GUI code tends not to be a productive task because of the complications that arise. The main complication is how to test the correctness of a user interface. Imagine a situation where clicking a button causes a table to be filled with data. Now imagine that when a check box is checked and the button is clicked again, a different table is filled with content. The fact that clicking the same button results in two ...
3. Understanding JavaScript and Types
Understanding JavaScript and Types Problem You want to work around the fact that JavaScript does not have types declared for its variables. Theory JavaScript code does not have any variables with a declared type. The lack of typed variables is apparent when you declare functions. That said, not having typed variable declarations does not mean JavaScript has no types or no type safety. Let’s start out with the simple declaration of a function, as illustrated by the following ex...
4. Coding Using Conventions and Not Configurations
Coding Using Conventions and Not Configurations Problem You want to make your JavaScript constructs more efficient by applying the Rails “convention over configuration” principle to them. Theory You may already be familiar with the programming platform Ruby on Rails, which is used to build Web applications. The focus of this recipe is not Ruby on Rails, but one aspect of Ruby on Rails namely, convention over configuration (see http://en.wikipedia.org/wiki/ Ruby_on_Rails for m...
5. Advantage of parameterless functions in JavaScript
Using Parameterless Functions Problem You want to take advantage of parameterless functions in JavaScript. Theory JavaScript functions for the most part have parameters. You may think that the previous sentence states the obvious after all, without parameters, what data could be passed to a function? JavaScript has the ability to declare functions that have no parameters, even though the caller of the function has passed parameters to the function. For example, let’s look at...
6. JavaScripot Functions
Treating Functions Like Objects Problem You want to take advantage of the fact that functions are objects (remember, everything is an object in JavaScript). Theory Many people think that a function is some keyword used in JavaScript. A function is also an object that can be manipulated. Knowing that a function is an object makes it very interesting from the perspective of writing JavaScript code, because the code can treat the function like another other object. This mean...
7. Implementing an Error and Exception Handling Strategy
Implementing an Error and Exception Handling Strategy Problem You want to implement a clean error and exception handling strategy in your applications, to make them run more smoothly. Theory Of course, you might argue that one error is a dialog box and the other is generated in the JavaScript console. The fact that one browser uses a dialog box to show an error and the other does not is a browser issue, not an error issue. A concise way of classifying the two errors is to ...
8. Understanding the Behavior of Variables When Implementing Recursion
Understanding the Behavior of Variables When Implementing Recursion Problem You want to implement recursion in JavaScript, and you also want to understand how variables will behave under those circumstances. Theory In JavaScript, you do not need to declare the variable type, or even declare the variable. For example, the following code works perfectly: if( counter == 1) { buffer = "counter is 1"; } document.getEle...
9. Using Functions to Initialize and Make Decisions JavaScript
Using Functions to Initialize and Make Decisions Problem You want to use functions to initialize and make decisions. Theory Usually when you write a piece of code where a change of logic needs to take place based on a context, you use a decision structure. For example, say you are implementing a light switch using a program. You turn on the light if the light is off, and you turn off the light if the light is on. The behavior of the program is determined by the conditions. One example behavior t...