DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest Languages Topics

article thumbnail
Parsing JavaScript with JavaScript
Over the weekend I started working on llamaduck- a simple tool that aims to figure out whether your code will run on the newly released node 0.6.0. Eventually, it might be able to perform other compatibility assessment tasks as well, but I’m focusing on simple stuff first. Or at least I thought it was simple. The list of API changes since 0.4.x doesn’t seem that long and it should be easy enough to digest. But as it turns out, I spent almost all of Sunday just figuring out how to turn javascript into a beautiful analyzable AST. If you don’t know what an AST is – it’s a so-called abstract syntax tree, which means it should look identical regardless of what the actual syntax is. Although it will differ for different languages. So a CoffeeScript AST should look the same as JavaScript, but Python’s will differ. JavaScript Alterations and Changes There are so many JavaScript alterations and changes that one may need to make as they work through the program that it is undoubtedly challenging for some people to keep up with precisely what they are supposed to do to take care of things like this. What is known is that JavaScript alterations and changes can make life a lot more challenging for you in the short term, but it will pay off with a better product in the long run. What I discovered was that there were a lot of changes that needed to be made to get JavaScript to line up just the way that I wanted it to. There are so many small and technical aspects of this kind of coding that need to be adhered to down to the letter, and it is certainly not easy to pull it off until one has a lot of time to sit down and figure out what they need to do. JavaScript remains the dominant language used by computer programmers to put their materials out onto the Internet, so it made a lot of sense to me to start using this as a primary tool to get my own work done as well. I have continued to rely on JavaScript for projects both large and small, and I know that the only way that I get the most possible value out of it is to use it in ways that are effective for my customers. The increased use of JavaScript for all programmers is something that has led me to believe that I must continue working on ways to make the most out of my time with this program and the skills that I know can be applied in the best ways possible to get my desired results. When running JavaScript through the actual JavaScript program, it is common for programmers to run into some common issues. There are lines of exceptions that may appear at times, and there are other situations that arise which make it obvious that a certain piece of code is just not going to work as desired. If you run into that problem, just know that this is what the process is all about. Running the JavaScript through the program first is a great way to make sure those errors and omissions are eliminated from the final product. Look over every piece of this very carefully and make sure you understand what you are looking at. You may just discover that there is a lot more that you could be doing to help out your users after all. My research came up with three options: Take a parser generator and a JavaScript grammar, and hope for the best JSLint has a parser … somewhere around line 2000 Uglify-JS supposedly has a parser too The only viable option was uglify-js. It’s a neatly packaged node.js module that does a bit more than I need, but at least it’s got an easy-to-use parser with an exposed API interface. Score! Here’s an example of a file that outputs its own AST to give you a feel for what I’m talking about: var parser = require('uglify-js').parser; var util = require('util'); (function get_ast (path, callback) { require('fs').readFile(path, 'utf-8', function (err, data) { if (err) throw err; callback(parser.parse(data)); }); })('./example.js', function (data) { console.log(util.inspect(data, true, null)); }); The file parses itself and outputs a tree encoded as a javascript array (scroll past the insanity, there’s a bit more text there): [ 'toplevel', [ [ 'var', [ [ 'parser', [ 'dot', [ 'call', [ 'name', 'require', [length]: 2 ], [ [ 'string', 'uglify-js', [length]: 2 ], [length]: 1 ], [length]: 3 ], 'parser', [length]: 3 ], [length]: 2 ], [length]: 1 ], [length]: 2 ], [ 'var', [ [ 'util', [ 'call', [ 'name', 'require', [length]: 2 ], [ [ 'string', 'util', [length]: 2 ], [length]: 1 ], [length]: 3 ], [length]: 2 ], [length]: 1 ], [length]: 2 ], [ 'stat', [ 'call', [ 'function', 'get_ast', [ 'path', 'callback', [length]: 2 ], [ [ 'stat', [ 'call', [ 'dot', [ 'call', [ 'name', 'require', [length]: 2 ], [ [ 'string', 'fs', [length]: 2 ], [length]: 1 ], [length]: 3 ], 'readFile', [length]: 3 ], [ [ 'name', 'path', [length]: 2 ], [ 'string', 'utf-8', [length]: 2 ], [ 'function', null, [ 'err', 'data', [length]: 2 ], [ [ 'if', [ 'name', 'err', [length]: 2 ], [ 'throw', [ 'name', 'err', [length]: 2 ], [length]: 2 ], undefined, [length]: 4 ], [ 'stat', [ 'call', [ 'name', 'callback', [length]: 2 ], [ [ 'call', [ 'dot', [ 'name', 'parser', [length]: 2 ], 'parse', [length]: 3 ], [ [ 'name', 'data', [length]: 2 ], [length]: 1 ], [length]: 3 ], [length]: 1 ], [length]: 3 ], [length]: 2 ], [length]: 2 ], [length]: 4 ], [length]: 3 ], [length]: 3 ], [length]: 2 ], [length]: 1 ], [length]: 4 ], [ [ 'string', './example.js', [length]: 2 ], [ 'function', null, [ 'data', [length]: 1 ], [ [ 'stat', [ 'call', [ 'dot', [ 'name', 'console', [length]: 2 ], 'log', [length]: 3 ], [ [ 'call', [ 'dot', [ 'name', 'util', [length]: 2 ], 'inspect', [length]: 3 ], [ [ 'name', 'data', [length]: 2 ], [ 'name', 'true', [length]: 2 ], [ 'name', 'null', [length]: 2 ], [length]: 3 ], [length]: 3 ], [length]: 1 ], [length]: 3 ], [length]: 2 ], [length]: 1 ], [length]: 4 ], [length]: 2 ], [length]: 3 ], [length]: 2 ], [length]: 3 ], [length]: 2 ] Conclusion Now we have a simple tree we can recursively analyze and look for incompatibilities. But before anything really practical can be done I need to figure out how to track variable scope. That’s really the hard bit because the code needs to check when variables become a critical section and then confirm that they do in fact eventually get used in a critical way. But once that nut is cracked llamaduck will be a neat little tool useful for many things. If you’ve got some coding inclination, I’d love a helping hand over at the llamaduck github repo. Related articles Lessons From A Review Of JavaScript Code (coding.smashingmagazine.com) ParserPlayground partial internals update (leuksman.com) Google Closure Introduction (googleclosure.wordpress.com) Announcing JesCov – JavaScript code coverage (olabini.com) Polyglot programming – combining functional, dynamic and imperative languages (mindscapehq.com)
August 13, 2022
by Swizec Teller
· 10,355 Views · 1 Like
article thumbnail
Migrate Serialized Java Objects with XStream and XMT
Java serialization is convenient to store the state of Java objects. However, there are some drawbacks of serialized data: It is not human-readable. It is Java-specific and is not exchangeable with other programming languages. It is not migratable if fields of the associated Java class have been changed. These drawbacks make Java serialization not a practical approach to storing object states for real-world projects. In a product developed recently, we use XStream to serialize/deserialize Java objects, which solves the first and second problems. The third problem is addressed with XMT, an open source tool developed by us to migrate XStream serialized XMLs. This article introduces this tool with some examples. Computer Languages Need to be Simplified So many of the issues that we all run into when we are working on converting computer languages into something that can be better understood by human beings is the fact that computer languages need to be simplified if possible. These languages are great for the computers that speak back and forth with one another, but they don’t necessarily work out as well when humans try to become involved with them. Many humans end up confused and unable to make much progress at all on getting these systems cleared up. Thus, it is necessary to get them cleaned up and made more usable. There are people who are actively working on this problem right now, but in the meantime, we may simply have to deal with computers that can’t do everything we would like for them to do. XStream deserialization problem when class is evolved Assume a Task class below with a prioritized field indicating whether it is a prioritized task: package example; public class Task { public boolean prioritized; } With XStream, we can serialize objects of this class to XML like below: import com.thoughtworks.xstream.XStream; public class Test { public static void main(String args[]) { Task task = new Task(); task.prioritized = true; String xml = new XStream().toXML(task); saveXMLToFileOrDatabase(xml); } private static void saveXMLToFileOrDatabase(String xml) { // save XML to file or database here } } The resulting XML will be: true And you can deserialize the XML to get back task object: import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; public class Test { public static void main(String args[]) { String xml = readXMLFromFileOrDatabase(); Task task = (Task) new XStream(new DomDriver()).fromXML(xml); } private static String readXMLFromFileOrDatabase() { // read XML from file or database here } } Everything is fine. Now we find that a prioritized flag is not enough, so we enhance the Task class to be able to distinguish between high priority, medium priority and low priority: package example; public class Task { enum Priority {HIGH, MEDIUM, LOW} public Priority priority; } However, deserialization of previously saved XML is no longer possible since the new Task class is not compatible with the previous version. How does XMT Address the Problem XMT comes to the rescue: it introduces the class VersionedDocument to version serialized XMLs and handles the migration. With XMT, serialization of task object can be written as: package example; import com.pmease.commons.xmt.VersionedDocument; public class Test { public static void main(String args[]) { Task task = new Task(); task.prioritized = true; String xml = VersionedDocument.fromBean(task).toXML(); saveXMLToFileOrDatabase(xml); } private static void saveXMLToFileOrDatabase(String xml) { // save XML to file or database here } } For task class of the old version, the resulting XML will be: true Compared with the XML generated previously with XStream, an additional attribute version is added to the root element indicating the version of the XML. The value is set to "0" unless there are migration methods defined in the class as we will introduce below. When Task class is evolved to use enum based priority field, we add a migrated method like the below: package example; import java.util.Stack; import org.dom4j.Element; import com.pmease.commons.xmt.VersionedDocument; public class Task { enum Priority {HIGH, MEDIUM, LOW} public Priority priority; @SuppressWarnings("unused") private void migrate1(VersionedDocument dom, Stack versions) { Element element = dom.getRootElement().element("prioritized"); element.setName("priority"); if (element.getText().equals("true")) element.setText("HIGH"); else element.setText("LOW"); } } Migration methods need to be declared as a private method with the name in the form of "migrateXXX", where "XXX" is a number indicating the current version of the class. Here method "migrate1" indicates that the current version of the Task class is of "1", and the method migrates the XML from version "0" to "1". The XML to be migrated is passed as a VersionedDocument object which implements the dom4j Document interface and you may use dom4j to migrate it to be compatible with the current version of the class. In this migration method, we read back the "prioritized" element of version "0", rename it as "priority", and set the value as "HIGH" if the task is originally a prioritized task; otherwise, set the value as "LOW". With this migration method defined, you can now safely deserialize the task object from XML: package example; import com.pmease.commons.xmt.VersionedDocument; public class Test { public static void main(String args[]) { String xml = readXMLFromFileOrDatabase(); Task task = (Task) VersionedDocument.fromXML(xml).toBean(); } private static String readXMLFromFileOrDatabase() { // read XML from file or database here } } The deserialization works not only for XML of the old version but also for XML of the new version. At deserialization time, XMT compares the version of the XML (recorded in the version attribute as we mentioned earlier) with the current version of the class (maximum suffix number of various migrate methods), and runs applicable migrate methods one by one. In this case, if an XML of version "0" is read, method migrate1 will be called; if an XML of version "1" is read, no migration methods will be called since it is already up to date. As the class keeps evolving, more migration methods can be added to the class by increasing the suffix number of the latest migration method. For example, let's further enhance our Task class so that the priority field is taking a numeric value ranging from "1" to "10". We add another migrate method to the Task class to embrace the change: @SuppressWarnings("unused") private void migrate2(VersionedDocument dom, Stack versions) { Element element = dom.getRootElement().element("priority"); if (element.getText().equals("HIGH")) element.setText("10"); else if (element.getText().equals("MEDIUM")) element.setText("5"); else element.setText("1"); } This method only handles the migration from version "1" to version "2", and we do not need to care about version "0" anymore, since the XML of version "0" will first be migrated to version "1" by calling the method migrate1 before running this method. With this change, you will be able to deserialize the task object from XML of the current version and any previous versions. This article demonstrates the idea of how to migrate field change of classes. XMT can handle many complicated scenarios, such as migrating data defined in multiple tiers of class hierarchy, addressing class hierarchy change, etc. For more information of XMT, please visit http://wiki.pmease.com/display/xmt/Documentation+Home
August 13, 2022
by Robin Shen
· 21,207 Views · 1 Like
article thumbnail
It's Official! Fat Arrows in JavaScript!
It’s official! We’re getting a new function syntax! The TC39 group (the panel charged with delivering ES 6) has reached a consensus on an abbreviated syntax for JavaScript function expressions. It's popularly known as the fat arrow syntax, and is based on a similar construct found in CoffeeScript. Make no mistake, I’m delighted that we will finally have an alternative to the unnecessary clunkiness and verbosity of the present grammar, but I can’t shake a nagging feeling that this proposal (in its current form) is flawed to the extent that it might actually make new developers more confused than they already were. I’ll run through the key features of this new construct, then explain my concerns and how they might be mitigated. There are Finally Fat Arrows in Java Java continues to add new features and make itself more useful to the public in due course. That said, there are many who have complained that the service never allowed them to put in the fat arrows that they wanted to. It was a glaring hole in the program, and it has now been clamped down on. People are finally able to get the fat arrow designs that they have been looking for without having to use another program to make it happen. Make sure you take a look at the full scope of what Java has to offer you as you explore the promise that it will be something even grander than anything else out on the marketplace at this time. You will want to take advantage of these new arrow designs if you can, and you will want to check up on all of the latest offerings from Java whenever possible. BS Alert Before starting out I should let you know that I’m going to make a lot of assertions about how fat arrows work. I’m reasonably confident that most of them are consistent with the latest proposal, but since research material is scant (I’m relying on the ES Wiki and the ES discuss list) and the examples are not testable (the traceur compiler does not yet support fat arrows) there are going to be some mistakes, for which I apologize upfront. I welcome corrections and will update the content as I get them. Thanks! How does it Work? The Syntax The fat arrow grammar has the following characteristics: 1. The arrow (=>) takes the place of the function keyword 2. Parameters are specified before the arrow, parentheses are required when there are zero, two or more parameters. 3. Block syntax (i.e. enclosing the function body in curly braces) is optional when the body comprises a single expression, otherwise it is required. 4. The return keyword is implied when the function body comprises a single expression. In all other cases returns must be used explicitly. Here are some simple examples. I’ve paired each fat arrow use case with the corresponding long-form syntax, although as we’ll see later the paired functions do not necessarily represent identical behavior. I’m defining variables with the var keyword for the sake of familiarity, but by the time ES6 is implemented you’re more likely to use let which allows variables to be defined with block scoping: //empty function var fat1 = () => {}; var long1 = function() {}; //return the square var fat2 = x => x * x; var long2 = function(x) {return x * x}; //add two numbers var fat3 = (a, b) => a + b; var long3 = function(a, b) {return a + b}; //return square root if x is a number, otherwise return x var fat4 = x => (typeof x == "number") ? Math.sqrt(x) : x; var long4 = function(x) { return (typeof x == "number") ? Math.sqrt(x) : x; }; Fat arrows bring a terse elegance to functional JavaScript… //return a new array containing the squares of the original... [1, 2, 3, 4, 5].map(x => x * x); //[1, 4, 9, 16, 25] //capitalize... ['caption', 'select', 'cite', 'article'].map(word => word.toUpperCase()); //['CAPTION', 'SELECT', 'CITE', 'ARTICLE'] //rewrite all instances of Fahrenheit as Celsius... function f2c(x) { var test = /(\d+(\.\d*)?)F\b/g; return x.replace(test, (str, val) => (val-32)*5/9 + "C"); } f2c("Store between 50F and 77F"); //"Store between 10C and 25C" (The last example is a rewrite of this traditional implementation). No Extras For You, Fat Arrow Not only do fat arrows use lightweight syntax – they also generate lightweight functions… No Constructors Functions created using fat arrow syntax have no prototype property, which means they can’t be used as constructors. If you try to use a fat arrow function as a constructor it throws a TypeError. No Arguments The argument’s object is not available within the execution context of a fat arrow function. This is not a huge loss; by the time ES 6 is in full swing, we can expect arguments to have been deprecated in favor of the rest (...) syntax. No Names There are Function Expressions, and then there are Named Function Expressions. Fat arrow functions have no place for a name, so they will always just be plain anonymous Function Expressions. The Value of This Functions defined with the fat arrow syntax have their context lexically bound; i.e. this value is set to the value of the enclosing scope (the outer function where present, otherwise the global object). //with long-form inner function var myObj = { longOuter: function() { console.log(this); //this is myObj var longInner = function() { console.log(this); //this is global object }; longInner(); } } myObj.longOuter(); //with fat arrow inner function var myObj = { longOuter: function() { console.log(this); //this is myObj var fatInner = () => console.log(this); //this is myObj fatInner(); } } myObj.longOuter(); It's a hard binding, which means if a fat arrow is used to define a method in an object literal it will continue to be bound to that object even when invoked from a borrowing object: var myObj = { myMethod: function() {return () => this;}, toString: () => "myObj" } var yourThievingObject = { hoard: myObj.myMethod, toString: () => "yourThievingObject" }; yourThievingObject.hoard(); //"myObj" Similarly the this value of a fat arrow function cannot be modified by means of call or apply: //traditional long inner function var myObj = { longOuter: function() { console.log(this); //this is myObj var longInner = function() { console.log(this); //this is now myOtherObj } longInner.call(myOtherObj); } } myOtherObj = {}; myObj.longOuter(); //new fat inner function var myObj = { longOuter: function() { console.log(this); //this is myObj var fatInner = () => console.log(this); //this is still myObj fatInner.call(myOtherObj); } } myOtherObj = {}; myObj.longOuter(); So What’s the Problem? If you trawl the JavaScript section of Stack Overflow, you’ll find dozens of questions from puzzled developers trying to get their heads around JavaScript’s somewhat byzantine process of this assignment. So…remember how there are five ways to define the value of this in a function?… Syntax of function call Value of this 1. Method call: myObject.foo(); myObject 2. Baseless function call: foo(); global object (e.g. window) (undefined in strict mode) 3. Using call: foo.call(context, myArg); context 4. Using apply: foo.apply(context, [myArgs]); context 5. Constructor with new: var newFoo = new Foo(); the new instance (e.g. newFoo) …well now there’s a sixth… Syntax of function call Value of this 6. Fat Arrow: (x => x*x)(); this of lexical parent (A seventh rule was also proposed – naming the first argument of a fat arrow as ‘this’ would have bound the context to the base reference of a method call – but thankfully that option has been deferred). I appreciate the rationale behind lexical this binding. It’s intuitive, and if JavaScript was starting over, this would not be a bad way to do it. But at this point I’ve fallen in love with dynamic this values; they make functions gloriously flexible and are a great compliment to functional patterns, wherein functions form the bedrock of data, and other objects are mere fungibles. Moreover, if new developers are already discouraged by JavaScript’s perceived arbitrary assignment of context, yet another rule might be enough to finish them off for good. Bear in mind that fat arrow is sugar, and a very tasty sugar at that; it will be eagerly devoured by many developers long before the consequences of the sixth law of this has time to sink in. There’s another, related issue with the current proposal. Legacy functions (third party or otherwise) generally assume that their function arguments have dynamic this values. This enables them to invoke function arguments in any given context, which, amongst other things, is a useful way to add mixins. It’s true that Function.prototype.bind already offers a form of hard binding, but it does so explicitly; on the other hand, fat arrow’s hard binding is a side effect and it’s not at all obvious that it would break code like this: function mixin(obj, fn) { fn.call(obj); } //long form function mixin is dynamically bound var withCircleUtilsLong = function() { this.area = function() {return this.radius * this.radius * Math.PI}; this.diameter = function() {return this.radius + this.radius}; } //fat arrow function mixin is lexically bound (to global object in this case) var withCircleUtilsFat = () => { this.area = function() {return this.radius * this.radius * Math.PI}; this.diameter = function() {return this.radius + this.radius}; } var CircularThing = function(r) {this.radius = r}; //utils get added to CircularThing.prototype mixin(CircularThing.prototype, withCircleUtilsLong); (new CircularThing(1)).area(); //3.14 //utils get added to global object mixin(CircularThing.prototype, withCircleUtilsFat); (new CircularThing(1)).area(); //area is undefined How to Fix It OK, enough whining; time to make some proposals. Here are three ideas to remove, or at least mitigate, any negative effects of the new fat arrow context behavior. 1) (This one’s easy). Have fat arrow functions define this the same way as any regular Function Expression does – i.e. according to the five rules in the table above. It’s worth noting that CoffeeScript defined fat arrow as an alternative to their thin arrow (->) syntax. Thin arrow in CoffeeScript behaves, by and large, the same way as regular JavaScript Function Expressions. In contrast, ES6′s fat arrow is attempting to do at least two things at once – be the sole abbreviator of the syntax and redefine context assignment. To do one, or the other, would be less confusing. 2) (You probably saw this one coming too). Introduce thin arrow syntax at the same time. That way developers are drawn to the safer, less radical sugar which simply abbreviates their Function Expressions without throwing in secret surprises that mess with their contexts. Fat arrow expressions become the special case, not the default. This mail suggested the difference between fat and thin arrow would confuse folks, but by removing thin arrow we remove the stepping stone between dynamically bound long form functions and hardbound short form functions and the necessary conceptual leap becomes more radical. 3) (This one was proposed by @fb55 on the es discuss list). Only employ lexical scoping as a fallback when no other this binding is suggested. In other words, this would take the value of the base reference in a method call, or the context passed with a call or apply, but would defer to lexical scoping when invoked as a standalone function. (Standalone functions might just be the only part of JavaScript this assignment that actually needs fixing anyway). Wrap Up Is the primary goal of arrow functions brevity? or a hard-lexical binding? If it’s the former (and even if it isn't, a lot of developers will perceive that it is) then we should be careful not to overload it with new or surprising behavior. Oh and follow @fat.
August 13, 2022
by Angus Croll
· 17,547 Views · 1 Like
article thumbnail
Write Your Kubernetes Infrastructure as Go Code - Extend cdk8s With Custom Constructs
Build a Wordpress deployment as a cdk8s construct.
August 12, 2022
by Abhishek Gupta DZone Core CORE
· 34,477 Views · 2 Likes
article thumbnail
Getting started with PHP framework codeigniter
I have always worked with core PHP and was always reluctant to use any CMS (Joomla, Drupal, etc). Coincidentally I never got a chance to work on any of the frameworks in PHP. But in the current project at work, we have decided to use CodeIgniter. CodeIgniter is a lightweight open source web application framework. In short, it gives you a directory structure of a proper MVC pattern along with a lightweight built-in templating engine of its own. MVC pattern helps developers to separate business logic and the presentation layer. It requires a very minimal setup, unlike the famous PHP framework, Zend. Zend is mostly used in developing enterprise applications and is a vast framework, hence making the learning curve more difficult. On the other hand, CodeIgniter is easy to set up and easier to learn. Using Proper Frameworks It is so very important to apply the proper frameworks to any project that you are working on. When you use the best coding frameworks, you can accomplish a lot more than you might have ever dreamed was possible. Eliminating some of the noise and distractions that can take you away from truly accomplishing all that you need to is a big step in the right direction, and you will find that getting started with the right frameworks is probably what you need to do as a first step towards that goal. Otherwise, you will find yourself floundering for the right answers, and your projects just won’t turn out the way that you might have hoped that they would. Let’s Get started with CodeIgniter Of course, the first step is to download the codeigniter framework. You can download the latest stable version of Codeigniter from the following URL http://codeigniter.com/downloads/ . It will be a compressed file (zip file) that will be downloaded, just unzip it and keep it in a folder, say Codeigniter. Make sure you keep it inside the htdocs or webserver’s directory. Now it's time to configure the Codeigniter which initial settings to start working on. To do so, open the file config.php in your favorite editor. The file resides inside system/application/config directory. You will see an array called $config which stores all the configuration information, we will change only the following values and leave the rest as it is. /* |-------------------------------------------------------------------------- | Base Site URL |-------------------------------------------------------------------------- | */ //don't forget the TRAILING slash (/) $config['base_url'] = "http://localhost/codeigniter/"; Trust me, that shall be all to get you started. Some blogs/sites have shown many changes in this file, but you can play around with them when needed. You can change a lot about your application from this single file. Like you can store the session information inside a database, by simply setting up the config var $config['sess_use_database'] as TRUE, which is FALSE by default. You can also change the name of the session table from default “ci_sessions” to anything you like. Since none of the web applications runs without database, let me show you how to configure a database in this setup. I decided to pick this up in the next tutorial, but since it's pretty straightforward, let’s do it. To configure the database, open database.php which is located in the same directory as config.php i.e. system/application/config . Now change the values of the following array keys with the actual values of your MySQL server. $active_group = "default"; $active_record = TRUE; $db['default']['hostname'] = "localhost"; $db['default']['username'] = ""; //database username $db['default']['password'] = ""; //database password $db['default']['database'] = ""; //name of the database $db['default']['dbdriver'] = "mysql"; $db['default']['dbprefix'] = ""; //any table prefix, if you want to keep one $db['default']['pconnect'] = TRUE; $db['default']['db_debug'] = TRUE; $db['default']['cache_on'] = FALSE; $db['default']['cachedir'] = ""; $db['default']['char_set'] = "utf8"; $db['default']['dbcollat'] = "utf8_general_ci"; As you see the database configuration was also simple. Now it's time to develop a simple application using the CI framework. At the very beginning of this post I mentioned that CodeIgniter gives you an MVC pattern structure, so every part has a separate folder. Let us create a simple controller class to start with. To do this, let's create a class called Hello which will be written in the file called hello.php, stored inside system/application/controllers/ folder. The content of the file can be : (you can have a different class, after all, it's just a PHP class). class hello extends Controller { function __construct() { //call parent constructor parent::__construct(); } function index() { $output['header'] = "My page's header"; $output['content'] = "Here is the content of the webpage"; //load from from the system/application/views/hello.php $this->load->view('hello',$output); } } Dissect the code Now let us understand the code line by line. It's a controller class called hello which extends the default parent class called Controller. Extending the Controller class facilitates the execution of this controller. The constructor of this call simply loads the constructor of the parent class, which apparently is Controller. Next is the index(); function which has a special meaning in the CI framework. If it's present in a controller, it is executed automatically when the controller is loaded/executed. Now we output the data using the view part of the MVC pattern. if you notice the above code loads a view called hello which is a file kept inside the system/application/views/ folder. The file name should be the same as the name of the controller. And the data is provided in the form of an array, where header,content are the template variables, as shown below in the hello.php The above view renders the data which is passed on by the calling controller. Now let's try and test if everything works as we expected, phew! Open your browser and hit http://localhost/codeigniter/index.php/hello/ If everything is well, you should see a webpage, with a header and body content as specified in the controller. Wonder, how did that get rendered? CodeIgniter provides a very nice routing mechanism based on REST. The URL is so that you can call a specific controller and a method from inside the controller. But if you notice, in the above URL we have mentioned only the controller name i.e. hello, and not the function name index(). As mentioned previously, This is due to the fact that index(); function gets called automatically if it exists. Might it have been another function called render then the above URL would have been changed to http://localhost/codeigniter/index.php/hello/render/ The above URL which now call the render(); function from the hello controller. CodeIgniter was easy, no? If you think that was tough, just go through the steps again and I am sure you will understand. Since CI is the easiest framework and it lets you get started very quickly with the development. Happy Development!
August 12, 2022
by Sachin Khosla
· 11,231 Views · 1 Like
article thumbnail
CoffeeScript: a TDD example
CoffeeScript is a language building an abstraction over JavaScript (as the similar name suggests.) It is an abstraction over the syntax of JavaScript, not over its concepts: the language is still based on functions as objects which may bind to other objects, and prototypical inheritance. CoffeeScript favors the best practices of JavaScript by transforming abstractions you would have written anyway, or borrowed from a framework, into language concepts for maximum conciseness. It has a compilation step - as every language must compile to a lower-level one, like C or Java. Since cowboy coding is not my preferred way to work, I prepared a Test-Driven Development example by using jsTestDriver. In this article, you get two things: a CoffeeScript introduction, and the tools for unit testing it (and consequently, how to TDD with CoffeeScript). Building on Top of JavaScript There is something to be said for those who go out of their way to try to improve the infrastructure of existing programs. Many have taken a stab at it by creating tools that are a compliment to JavaScript, and it appears to have worked quite well in this case. The reason? Because JavaScript is in need of some improvements. One of the programs that people have come up with is CoffeeScript. It is literally a bit of computer code that overlays the existing JavaScript codes to make it read even more fluidly. The benefit that one gets from this is that they can start to use JavaScript in a more efficient way with fewer bumps in the road. As it stands right now, JavaScript has numerous challenging issues that we must recognize. However, that can all be amended by using JavaScript as it was intended and just working towards perfecting it. CoffeeScript is certainly not the end all be all of the programs for improving JavaScript, but it is a great step in the right direction. People should at least try out the CoffeeScript code to see if it may be useful to them in terms of improving the quality of codes that they receive from JavaScript. If so, then it will have been worth the trouble. The infrastructure The basic structure consists of two folders: src/ and lib/; remember the compilation step. We'll put .coffee files into src/ and compile them to .js equivalents in a symmetrical tree in lib/. We add also a jsTestDriver.conf file to tell the unit testing framework all the files to load, which are only the "binary" .js scripts: server: http://localhost:4224 load: - lib/*.js Compiling This is the first version of the test I've managed to write, fizzbuzztest.coffee. It is a tautology that should always pass: mytest = () -> assertEquals(1, 1) tests = { "test1is1": mytest } TestCase("tests for fizzbuzz kata", tests) You see here that functions are still first-class objects, but only anonymous functions are supported. CoffeeScript is a Python/Ruby-like language without semicolons, and there are some affinities and common backgrounds with the latter language. I still use the old syntax for calling functions for now, although parentheses can be omitted in many cases. CoffeeScript is conservative, and even accepts semicolons if you want to write them. I compiled this script with coffee -o lib/ -c src/. fizzbuzztest.js is the result: (function(){ var mytest, tests; mytest = function() { return assertEquals(1, 1); }; tests = { "test1is1": mytest }; TestCase("tests for fizzbuzz kata", tests); })(); The global namespace is not touched by default, and var keywords are automatically introduced to preserve it. When I later needed the global namespace, I wrote: this.fizzbuzz = /* ... function definition ... */ This in this case is the window object or the other global object where you execute the code. Running To run the test, we must initialize the test driver (only once): jsTestDriver java -jar JsTestDriver-1.3.2.jar --port 4224 jsTestDriver will now listen at localhost:4224. Load this URL in your browser and capture it by clicking on the link. Tests will be executed inside the browser when requested: for more details see the related article. Every time you want to run the tests, execute them from the command line: java -jar JsTestDriver-1.3.2.jar --tests all This is the complete history of my kata. Here is the final version of the code (spoiler alert!), with support for addition of other factors than 3 or 5. The code is probably uglier than average, but it compiles: tests = { "test ordinary numbers are unchanged": -> assertEquals(1, fizzbuzz(1)) assertEquals(2, fizzbuzz(2)) assertEquals(4, fizzbuzz(4)) assertEquals(142, fizzbuzz(142)) "test multiples of 3 become fizz": -> assertEquals("Fizz", fizzbuzz(3)) assertEquals("Fizz", fizzbuzz(6)) assertEquals("Fizz", fizzbuzz(9)) "test multiples of 5 become buzz": -> assertEquals("Buzz", fizzbuzz(5)) assertEquals("Buzz", fizzbuzz(10)) "test multiples of 3 and 5 become fizzbuzz": -> assertEquals("FizzBuzz", fizzbuzz(15)) assertEquals("FizzBuzz", fizzbuzz(45)) } TestCase("tests for fizzbuzz kata", tests) newRule = (word, divisor) -> (number) -> return word if number % divisor == 0 "" newFizzBuzz = (rules) -> (number) -> result = "" concatenation = (rule) -> result = result + rule(number) concatenation rule for rule in rules return result if result number fizzRule = newRule("Fizz", 3) buzzRule = newRule("Buzz", 5) this.fizzbuzz = newFizzBuzz([fizzRule, buzzRule]) Comments On The Experience CoffeeScript offers a shorter syntax, which presents a bit of a learning curve but not a steep one. I went through the whole example in 1 hour (I already knew how to use jsTestDriver, however.) Syntax shapes how you write code by making some things easier: I found myself using higher-order functions which create other ones more often, since creating a function now is just a matter of putting -> before some lines of code. Variable naming is also simpler as you just have to think of the name, not about var or polluting the scope. More time to dedicate to design, and less to language issues. Some one-liners like the instruction if the expression is handy but not essential, and are there due to Ruby's inspiration. There's, even more, to discover in CoffeeScript, such as the options for the binding of functions which helps not to lose the reference to this. However, the question is if all this convenience has more value than the time spent to learn a new language and add infrastructure to make it work - the compiler, the build hooks, and the parallel tree to ignore in your version control system.
August 12, 2022
by Giorgio Sironi
· 15,765 Views · 1 Like
article thumbnail
Clojure: Destructuring
In The Joy of Clojure (TJoC) destructuring is described as a mini-language within Clojure. It's not essential to learn this mini-language; however, as the authors of TJoC point out, destructuring facilitates concise, elegant code. Making Code More Understandable One of the scariest things for those who are just now learning how to do some coding is the fact that they have to try to figure out what a seemingly impossible set of rules and structures means for the work that they are trying to do. It is not easy at all, and many people struggle with it in big ways. Fortunately, there are some people who are going about the process of destructuring code so that it may be broken into smaller and more manageable chunks. If this is to happen, then one can easily see how they can potentially get a lot more value from the process of coding, and even how they can contribute to it for themselves in the future. We need to be as encouraging of the next generation of coders as we possibly can because there is no question that they will ultimately have an outsized impact on how the future of coding is decided. If they are best set up to understand coding and to make sense of its many intricacies, then they will be able to handle it without problems. However, we need to support and encourage them along the way, and that all begins by making coding easier to understand in general. What is destructuring? Clojure supports abstract structural binding, often called destructuring, in let binding lists, fn parameter lists, and any macro that expands into a let or fn. -- http://clojure.org/special_forms The simplest example of destructuring is assigning the values of a vector. user=> (def point [5 7]) #'user/point user=> (let [[x y] point] (println "x:" x "y:" y)) x: 5 y: 7 note: I'm using let for my examples of destructuring; however, in practice, I tend to use destructuring in function parameter lists at least as often, if not more often. I'll admit that I can't remember ever using destructuring like the first example, but it's a good starting point. A more realistic example is splitting a vector into a head and a tail. When defining a function with an arglist** you use an ampersand. The same is true in destructuring. user=> (def indexes [1 2 3]) #'user/indexes user=> (let [[x & more] indexes] (println "x:" x "more:" more)) x: 1 more: (2 3) It's also worth noting that you can bind the entire vector to a local using the :as directive. user=> (def indexes [1 2 3]) #'user/indexes user=> (let [[x & more :as full-list] indexes] (println "x:" x "more:" more "full list:" full-list)) x: 1 more: (2 3) full list: [1 2 3] Vector examples are the easiest; however, in practice I find myself using destructuring with maps far more often. Simple destructuring on a map is as easy as choosing a local name and providing the key. user=> (def point {:x 5 :y 7}) #'user/point user=> (let [{the-x :x the-y :y} point] (println "x:" the-x "y:" the-y)) x: 5 y: 7 As the example shows, the values of :x and :y are bound to locals with the names the-x and the-y. In practice we would never prepend "the-" to our local names; however, using different names provides a bit of clarity for our first example. In production code you would be much more likely to want locals with the same name as the key. This works perfectly well, as the next example shows. user=> (def point {:x 5 :y 7}) #'user/point user=> (let [{x :x y :y} point] (println "x:" x "y:" y)) x: 5 y: 7 While this works perfectly well, creating locals with the same name as the keys become tedious and annoying (especially when your keys are longer than one letter). Clojure anticipates this frustration and provides :keys directive that allows you to specify keys that you would like as locals with the same name. user=> (def point {:x 5 :y 7}) #'user/point user=> (let [{:keys [x y]} point] (println "x:" x "y:" y)) x: 5 y: 7 There are a few directives that work while destructuring maps. The above example shows the use of :keys. In practice I end up using :keys the most; however, I've also used the :as directive while working with maps. The following example illustrates the use of an :as directive to bind a local with the entire map. user=> (def point {:x 5 :y 7}) #'user/point user=> (let [{:keys [x y] :as the-point} point] (println "x:" x "y:" y "point:" the-point)) x: 5 y: 7 point: {:x 5, :y 7} We've now seen the :as directive used for both vectors and maps. In both cases, the locale is always assigned to the entire expression that is being destructured. For completeness I'll document the :or directive; however, I must admit that I've never used it in practice. The :or directive is used to assign default values when the map being destructured doesn't contain a specified key. user=> (def point {:y 7}) #'user/point user=> (let [{:keys [x y] :or {x 0 y 0} point] (println "x:" x "y:" y)) x: 0 y: 7 Lastly, it's also worth noting that you can destructure nested maps, vectors and a combination of both. The following example destructures a nested map user=> (def book {:name "SICP" :details {:pages 657 :isbn-10 "0262011530"}) #'user/book user=> (let [{name :name {pages :pages isbn-10 :isbn-10} :details} book] (println "name:" name "pages:" pages "isbn-10:" isbn-10)) name: SICP pages: 657 isbn-10: 0262011530 As you would expect, you can also use directives while destructuring nested maps. user=> (def book {:name "SICP" :details {:pages 657 :isbn-10 "0262011530"}) #'user/book user=> user=> (let [{name :name {:keys [pages isbn-10]} :details} book] (println "name:" name "pages:" pages "isbn-10:" isbn-10)) name: SICP pages: 657 isbn-10: 0262011530 Destructuring nested vectors is also very straight-forward, as the following example illustrates user=> (def numbers [[1 2][3 4]]) #'user/numbers user=> (let [[[a b][c d]] numbers] (println "a:" a "b:" b "c:" c "d:" d)) a: 1 b: 2 c: 3 d: 4 Since binding forms can be nested within one another arbitrarily, you can pull apart just about anything -- http://clojure.org/special_forms The following example destructures a map and a vector at the same time. user=> (def golfer {:name "Jim" :scores [3 5 4 5]}) #'user/golfer user=> (let [{name :name [hole1 hole2] :scores} golfer] (println "name:" name "hole1:" hole1 "hole2:" hole2)) name: Jim hole1: 3 hole2: 5 The same example can be rewritten using a function definition to show the simplicity of using destructuring in parameter lists. user=> (defn print-status [{name :name [hole1 hole2] :scores}] (println "name:" name "hole1:" hole1 "hole2:" hole2)) #'user/print-status user=> (print-status {:name "Jim" :scores [3 5 4 5]}) name: Jim hole1: 3 hole2: 5 There are other (less used) directives and deeper explanations available on http://clojure.org/special_forms and in The Joy of Clojure. I recommend both. **(defn do-something [x y & more] ... )
August 12, 2022
by Jay Fields
· 15,167 Views · 1 Like
article thumbnail
Rust’s Ownership and Borrowing Enforce Memory Safety
By using an ownership model, Rust takes a novel approach to ensure memory safety at compile time.
August 11, 2022
by Senthil Nayagan
· 5,534 Views · 2 Likes
article thumbnail
Introduction: Querydsl vs. JPA Criteria
This article presents an introduction to the Querydsl series with the goal to highlight the difference from JPA Criteria.
Updated August 9, 2022
by Arnošt Havelka DZone Core CORE
· 19,950 Views · 8 Likes
article thumbnail
Snake-Based REST API (Python, Mamba, Hydra, and Fast API)
Using Python, Fast API, Hydra, and Mamba to build dockerized applications.
August 9, 2022
by Bartłomiej Żyliński DZone Core CORE
· 8,683 Views · 4 Likes
article thumbnail
Massively Scalable Geographic Graph Analytics: InfiniteGraph and Uber’s Hexagonal Hierarchical Spatial Index
In this article, learn how InfiniteGraph was used to build an implementation of the H3 Hexagonal Hierarchical Spatial Index.
August 9, 2022
by Daniel Hall
· 5,496 Views · 1 Like
article thumbnail
How to Build Spark Lineage for Data Lakes
Better understand the intricacies of Spark and how to build a lineage graph for data lakes.
August 8, 2022
by Lior Gavish
· 5,060 Views · 1 Like
article thumbnail
Build a Java Microservice With AuraDB Free
For today’s adventure, we want to build a Java microservice that connects to, and interacts with, graph data in a Neo4j AuraDB Free database.
Updated August 8, 2022
by Jennifer Reif DZone Core CORE
· 10,033 Views · 5 Likes
article thumbnail
Event Loop in JavaScript
JavaScript is single-threaded, meaning only one action can be performed at a time. Event Loop is the queue of commands to be called.
August 8, 2022
by Sebastian Z.
· 6,241 Views · 2 Likes
article thumbnail
ExpectedConditions in Selenium
In this Selenium tutorial, you will learn how to use Expected Conditions in Selenium to fix timing-related issues due to the dynamic loading of WebElements.
August 6, 2022
by Himanshu Sheth DZone Core CORE
· 12,403 Views · 3 Likes
article thumbnail
Handling File Uploads With NestJS and MySQL
Many developers despise dealing with file uploads. In this blog, we will teach you how to build a file uploading functionality using NestJS and MySQL.
August 6, 2022
by Clara Ekekenta
· 6,310 Views · 1 Like
article thumbnail
Amazon Lightsail: Virtual Cloud Server
Take an in-depth at topics relating to Amazon Lightsail, such as virtual private server basics, getting started with Lightsail, and Lightsail container service.
August 5, 2022
by Jawad Hasan Shani DZone Core CORE
· 9,297 Views · 3 Likes
article thumbnail
Spark-Radiant: Apache Spark Performance and Cost Optimizer
In this article, learn how to boost performance, reduce cost and increase observability for Spark Application using Spark-Radiant.
Updated August 5, 2022
by Saurabh Chawla
· 5,525 Views · 1 Like
article thumbnail
Diving Deep into Smart Contracts
Smart contracts allow two parties to enter into an agreement. Take a deep dive into smart contracts to see how to reuse a single contract over and over again.
August 5, 2022
by John Vester DZone Core CORE
· 76,790 Views · 5 Likes
article thumbnail
The Challenges of Ajax CDN
Learn why it’s no longer a best practice to host JavaScript a content delivery network (CDN) due to security considerations, network penalties, and to avoid a single point of failure.
August 5, 2022
by Mehdi Daoudi
· 8,636 Views · 1 Like
  • Previous
  • ...
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • ...
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×