Web and software consultant, open source advocate, teacher, event organizer. Helping make @FreeMusicNinja and @EditorConfig happen.
13 stories
·
1 follower

Simpler CLI tools

1 Share

grep, find, sed, awk are powerful and fast, but their APIs are hard to memorize and sometimes very awkward; so that’s why I use some tools that are slower but are way more user friendly.

Haters gonna hate, and there is definitely a hidden cost on using theses tools (you won’t learn the standard ones); but there is also a huge benefit on the ease of use.

Here are the tools that I use often:

z
jump between frequently used folders with ease (must have!).
ffind
searches for files by name inside a directory based on pattern.
spot
search for files that contains a given string.
ag
similar to spot but with more features. (worse output on minified files tho)
replace
search-and-replace on files. It’s similar to sed but uses JS RegExp
syntax, modifies files in place & recursive search on directories with -r.
the preview -p flag is really helpful.
http-server
basic static server, simpler than starting apache or python SimpleHTTPServer
(and can handle more requests than SimpleHTTPServer).
tldr
simplified help for common command line tools (man pages are usually verbose and hard to understand).
greadme
preview Github README/markdown files locally.
sloc
counts SLOC (source lines of code) inside a folder.
wr
watch files and run a command when they change
disparity
colored file diff, better than diff(1) when comparing white-spaces,
indentation and line breaks (output is easier to understand).

Not saying these are the best ones for the job, just that they do help me to do what I need. I’m by no means an UNIX/shell expert.

I hope these tools also help you do your job faster.

Cheers.

Read the whole story
treyhunner
3334 days ago
reply
San Diego, CA
Share this story
Delete

Idea: Extending native DOM prototypes without collisions

1 Share

As I pointed out in yesterday’s blog post, one of the reasons why I don’t like using jQuery is its wrapper objects. For jQuery, this was a wise decision: Back in 2006 when it was first developed, IE releases had a pretty icky memory leak bug that could be easily triggered when one added properties to elements. Oh, and we also didn’t have access to element prototypes on IE back then, so we had to add these properties manually on every element. Prototype.js attempted to go that route and the result was such a mess that they decided to change their decision in Prototype 2.0 and go with wrapper objects too. There were even long essays being written back then about how much of a monumentally bad idea it was to extend DOM elements.

The first IE release that exposed element prototypes was IE8: We got access to Node.prototype, Element.prototype and a few more. Some were mutable, some were not. On IE9, we got the full bunch, including HTMLElement.prototype and its descendants, such as HTMLParagraphElement. The memory leak bugs were mitigated in IE8 and fixed in IE9. However, we still don’t extend native DOM elements, and for good reason: collisions are still a very real risk. No library wants to add a bunch of methods on elements, it’s just bad form. It’s like being invited in someone’s house and defecating all over the floor.

But what if we could add methods to elements without the chance of collisions? (well, technically, by minimizing said chance). We could only add one property to Element.prototype, and then hang all our methods on that. E.g. if our library was called yolo and had two methods, foo() and bar(), calls to it would look like:

var element = document.querySelector(".someclass");
element.yolo.foo();
element.yolo.bar();
// or you can even chain, if you return the element in each of them!
element.yolo.foo().yolo.bar();

Sure, it’s more awkward than wrapper objects, but the benefit of using native DOM elements is worth it if you ask me. Of course, YMMV.

It’s basically exactly the same thing we do with globals: We all know that adding tons of global variables is bad practice, so every library adds one global and hangs everything off of that.

However, if we try to implement something like this in the naïve way, we will find that it’s kind of hard to reference the element used from our namespaced functions:

Element.prototype.yolo = {
	foo: function () {
		console.log(this); 
	},
	
	bar: function () { /* ... */ }
};

someElement.yolo.foo(); // Object {foo: function, bar: function}

What happened here? this inside any of these functions refers to the object that they are called on, not the element that object is hanging on! We need to be a bit more clever to get around this issue.

Keep in mind that this in the object inside yolo would have access to the element we’re trying to hang these methods off of. But we’re not running any code there, so we’re not taking advantage of that. If only we could get a reference to that object’s context! However, running a function (e.g. element.yolo().foo()) would spoil our nice API.

Wait a second. We can run code on properties, via ES5 accessors! We could do something like this:

Object.defineProperty(Element.prototype, "yolo", {
	get: function () {
		return {
			element: this,
			foo: function() {
				console.log(this.element);
			},
			
			bar: function() { /* ... */ }
		}
	},
	configurable: true,
	writeable: false
});

someElement.yolo.foo(); // It works! (Logs our actual element)

This works, but there is a rather annoying issue here: We are generating this object and redefining our functions every single time this property is called. This is a rather bad idea for performance. Ideally, we want to generate this object once, and then return the generated object. We also don’t want every element to have its own completely separate instance of the functions we defined, we want to define these functions on a prototype, and use the wonderful JS inheritance for them, so that our library is also dynamically extensible. Luckily, there is a way to do all this too:

var Yolo = function(element) {
	this.element = element;
};

Yolo.prototype = {
	foo: function() {
		console.log(this.element);
	},
	
	bar: function() { /* ... */ }
};

Object.defineProperty(Element.prototype, "yolo", {
	get: function () {
		Object.defineProperty(this, "yolo", {
			value: new Yolo(this)
		});
		
		return this.yolo;
	},
	configurable: true,
	writeable: false
});

someElement.yolo.foo(); // It works! (Logs our actual element)

// And it’s dynamically extensible too!
Yolo.prototype.baz = function(color) {
	this.element.style.background = color;
};

someElement.yolo.baz("red") // Our element gets a red background

Note that in the above, the getter is only executed once. After that, it overwrites the yolo property with a static value: An instance of the Yolo object. Since we’re using Object.defineProperty() we also don’t run into the issue of breaking enumeration (for..in loops), since these properties have enumerable: false by default.

There is still the wart that these methods need to use this.element instead of this. We could fix this by wrapping them:

for (let method in Yolo.prototype) {
	Yolo.prototype[method] = function(){
		var callback = Yolo.prototype[method];
		
		Yolo.prototype[method] = function () {
			var ret = callback.apply(this.element, arguments);
			
			// Return the element, for chainability!
			return ret === undefined? this.element : ret;
		}
	}
}

However, now you can’t dynamically add methods to Yolo.prototype and have them automatically work like the native Yolo methods in element.yolo, so it kinda hurts extensibility (of course you could still add methods that use this.element and they would work).

Thoughts?

Read the whole story
treyhunner
3334 days ago
reply
San Diego, CA
Share this story
Delete

jQuery considered harmful

2 Shares

Heh, I always wanted to do one of those “X considered harmful” posts*. :D

Before I start, let me say that I think jQuery has helped tremendously to move the Web forward. It gave developers power to do things that were previously unthinkable, and pushed the browser manufacturers to implement these things natively (without jQuery we probably wouldn’t have document.querySelectorAll now). And jQuery is still needed for those that cannot depend on the goodies we have today and have to support relics of the past like IE8 or worse.

However, as much as I feel for these poor souls, they are the minority. There are tons of developers that don’t need to support old browsers with a tiny market share. And let’s not forget those who aren’t even Web professionals: Students and researchers not only don’t need to support old browsers, but can often get by just supporting a single browser! You would expect that everyone in academia would be having tons of fun using all the modern goodies of the Open Web Platform, right? And yet, I haven’t seen jQuery being so prominent anywhere else as much as it is in academia. Why? Because this is what they know, and they really don’t have the time or interest to follow the news on the Open Web Platform. They don’t know what they need jQuery for, so they just use jQuery anyway. However, being able to do these things natively now is not the only reason I’d rather avoid jQuery.

Yes, you probably don’t really need it…

I’m certainly not the first one to point out how much of jQuery usage is about things you can do natively, so I won’t spend time repeating what others have written. Just visit the following and dive in:

I will also not spend time talking about file size or how much faster native methods are. These have been talked about before. Today, I want to make a point that is not frequently talked about…

…but that’s not even the biggest reason not to use it today

To avoid extending the native element prototypes, jQuery uses its own wrapper objects. Extending native objects in the past was a huge no-no, not only due to potential collisions, but also due to memory leaks in old IE. So, what is returned when you run $("div") is not a reference to an element, or a NodeList, it’s a jQuery object. This means that a jQuery object has completely different methods available to it than a reference to a DOM element, an array with elements or any type of NodeList. However, these native objects come up all the time in real code — as much as jQuery tries to abstract them away, you always have to deal with them, even if it’s just wrapping them in $(). For example, the context when a callback is called via jQuery’s .bind() method is a reference to an HTML element, not a jQuery collection. Not to mention that often you use code from multiple sources — some of them assume jQuery, some don’t. Therefore, you always end up with code that mixes jQuery objects, native elements and NodeLists. And this is where the hell begins.

If the developer has followed a naming convention for which variables contain jQuery objects (prepending the variable names with a dollar sign is the common one I believe) and which contain native elements, this is less of a problem (humans often end up forgetting to follow such conventions, but let’s assume a perfect world here). However, in most cases no such convention is followed, which results in the code being incredibly hard to understand by anyone unfamiliar with it. Every edit entails a lot of trial and error now (“Oh, it’s not a jQuery object, I have to wrap it with $()!” or “Oh, it’s not an element, I have to use [0] to get an element!”). To avoid such confusion, developers making edits often end up wrapping anything in $() defensively, so throughout the code, the same variable will have gone through $() multiple times. For the same reason, it also becomes especially hard to refactor jQuery out of said code. You are essentially locked in.

Even if naming conventions have been followed, you can’t just deal only with jQuery objects. You often need to use a native DOM method or call a function from a script that doesn’t depend on jQuery. Soon, conversions to and from jQuery objects are all over the place, cluttering your code.

In addition, when you add code to said codebase, you usually end up wrapping every element or nodelist reference with $() as well, because you don’t know what input you’re getting. So, not only you’re locked in, but all future code you write for the same codebase is also locked in.

Get any random script with a jQuery dependency that you didn’t write yourself and try to refactor it so that it doesn’t need jQuery. I dare you. You will see that your main issue will not be how to convert the functionality to use native APIs, but understanding what the hell is going on.

A pragmatic path to JS nudity

Sure, many libraries today require jQuery, and like I recently tweeted, avoiding it entirely can feel like you’re some sort of digital vegan. However, this doesn’t mean you have to use it yourself. Libraries can always be replaced in the future, when good non-jQuery alternatives become available.

Also, most libraries are written in such a way that they do not require the $ variable to be aliased to jQuery. Just call jQuery.noConflict() to reclaim the $ variable and be able to assign it to whatever you see fit. For example, I often define these helper functions, inspired from the Command Line API:

// Returns first element that matches CSS selector {expr}.
// Querying can optionally be restricted to {container}’s descendants
function $(expr, container) {
	return typeof expr === "string"? (container || document).querySelector(expr) : expr || null;
}

// Returns all elements that match CSS selector {expr} as an array.
// Querying can optionally be restricted to {container}’s descendants
function $$(expr, container) {
	return [].slice.call((container || document).querySelectorAll(expr));
}

In addition, I think that having to type jQuery instead of $ every time you use it somehow makes you think twice about superfluously using it without really needing to, but I could be wrong :)

Also, if you actually like the jQuery API, but want to avoid the bloat, consider using Zepto.

* I thought it was brutally obvious that the title was tongue-in-cheek, but hey, it’s the Internet, and nothing is obvious. So there: The title is tongue-in-cheek and I’m very well aware of Eric’s classic essay against such titles.

Read the whole story
treyhunner
3334 days ago
reply
San Diego, CA
Share this story
Delete

Red Hat and the Open Source Community

1 Share

Red Hat has a pretty interesting business model, which is offering support for software that is a decade old, and which its maintainers want nothing to do with. This post isn't about whether maintaining old software is a good or a bad idea. It's about the effect it has on the community.

The Python core developers have ceased providing any support for Python 2.6 as of October 2013, but Red Hat will continue to support it in RHEL 5, until 2020.1

Many Python projects (such as Django, Twisted, and PyCA Cryptography) are therefore looking to drop 2.6 support, to lighten their maintenance burden and because offering support for an unsupported platform is misleading to users.

This is where we hit an impasse; inevitably users of these projects ask for some level of support for a version of the library that supports 2.6, because they are using RHEL which has them pinned on Python 2.6. Red Hat supports their Python, but not the Python libraries they use.

While Python is a nice language, without the libraries of PyPI it is useless: no scientific computing, no machine learning, no websites, no access to your production database, no AWS bindings, no timezone database, no SSH automation, the list goes on.

Red Hat's business model fundamentally relies on the open source community offering free labor to support them. Red Hat does not continue to support Python 2.6 by working with the Python core development team to extend its life cycle. This means if something like PyCA Cryptography were to support Python 2.6, the entire stack would only be supported for Red Hat's customers, other individuals who had Python 2.6 would be on an unsupported platform.

This assumption of uncompensated labor to support Red Hat's business is inequitable. Open Source projects should not feel compelled to support older versions of software which are only supported commercially. Red Hat itself needs to consider ways it can continue to offer its support services, without them becoming burdensome to the open source community. Lastly, Red Hat customers who wish they could use newer versions of software, should consider either compiling it themselves, complaining to whoever procured RHEL for them, or complaining to Red Hat itself, but please don't demand support from already overburdened volunteers.

[1]Technically, RHEL 5 actually comes with Python 2.4, which was last updated in 2008. However, Python 2.6 can be installed via EPEL, which isn't officially supported by Red Hat, but is usually maintained by Fedora developers who work for Red Hat. RHEL 6 officially supports Python 2.6, and Python 2.7 can be obtained via EPEL for it.
Read the whole story
treyhunner
3334 days ago
reply
San Diego, CA
Share this story
Delete

Annotated Version of the Original jQuery Release

1 Comment and 3 Shares

Recently I was prompted by Daniel Lamb to try and find old versions of jQuery for his jQuery Archive project. Thankfully I was able to find one in the Internet Archive from just a couple weeks after its release, in January 2006.

I then took that opportunity to put that code online and I used the new Genius annotation beta to mark it up with a bunch of thoughts and memories around the release of the code.

Annotated jQuery Release

The comments are kind of sprawling, they cover the code itself to the circumstances of the release. I’ll certainly add more as I think of them. Please feel free to ask questions if there are certain things that you want to learn about!

One of the things I was most touched about was just how obviously inspired I was by many great developers who came before me. I’m glad I went out of my way to credit them on the original version of the jQuery site. jQuery would not have existed if it wasn’t for Sam Stephenson creating Prototype, Simon Willison creating getElementsBySelector, Valerio Proietti creating moo.fx, and especially Dean Edwards creating so much: event binding, CSS selector libraries, DOM ready techniques and more. I cover a lot of these influences in the annotations but I want to especially thank them now as without their work I never would’ve made jQuery.

Read the whole story
treyhunner
3342 days ago
reply
original jQuery source code annotated
San Diego, CA
Share this story
Delete

Letters to a Young Developer, pt. 1

1 Share

I love programming, I really do. I like making stuff work, I like when I finally wrap my head around a concept, I really like rubber-ducking with people. Since I love it so much, I can get pretty excited when someone tells me they're learning to program. And I get even more excited when they ask me for advice. Vainly, it makes me feel good that someone thinks I know enough that they might want to take my advice.

Often people ask "What do you wish you had known when you were #{insert stage/job/etc here}?" So this is "Letters to a Young Developer". The series of blog posts and advice I wish I'd come into when I was first #{insert stage/job/etc here}.

What Should I Learn Next?

"What should I learn next?" This was the question I asked once I'd finished a few of the recommended tutorials for new Ruby/Rails developers. At that time I was thinking I needed to practice certain techniques, learn how to implement certain features. For a long time when people asked me what they should learn next I would rattle off a laundry list of my favorite tutorials and guides. I assured them (as I had been assured myself not so many months before) that picking up another programming language was easy after the first one or two.

What I didn't think about though, was why it was easier to pick up another language after you had already learned one. I had the benefit of having a little bit of experience on my side, so I was familiar with the concept of debugging. What I didn't realize that what I was missing was understanding how to effectively debug in Ruby.

As I get more opportunities to work with other beginners, the difficulties of really learning and understanding a first language become much clearer to me. Even across different learning types, it seems like beginners' struggles circle around a few themes:

  1. recognizing patterns
  2. understanding syntax
  3. figuring out what went wrong

The first two, I think can be learned through writing code and reading. The last one is a little trickier. Sure, if you know a lot about design you can probably reason your way through what you think went wrong. But even with tests in place, sometimes your best guess is just that, a guess.

What I Wish I Knew

What I wanted to learn when I was asking "What should I learn next?", was really "How can I learn what's really going on?". My problem was I could implement the same things I had implemented before but I was nervous about implementing new things as I wasn't sure how to do them without a guide. Because at the end of the day, when you understand the language you can really learn how to implement almost any feature.

Think about when you work with someone (or when you worked on things) and something goes wrong they(or you) say "That keeps happening & I don't know why". They've tried this several times before and gotten the same error but the error doesn't mean anything to them because they don't know how to read it. This was me when I was first starting to write applications outside of the safety and guidance of tutorials. I knew something was wrong but I didn't know how to troubleshoot it.

Learning to Troubleshoot

The advice I'd give young Kylie (just a year & a half ago) would be learn how to troubleshoot. The very first thing I'd recommend to learn how to do this would be watching Blithe Rocher's Scientific Method of Troubleshooting. Developers seem to value methodical approaches to problem solving, so this is the perfect marriage of development and learning. For other new Ruby developers I'd recommend Jonathan Wallace's Effective Debugging in Ruby and this presentation by Melissa Holmes on Pry for Ruby. Learning how to debug effectively can make the difference between feeling like you're floundering and being able to move on quickly from mistakes. I know for me at least, being able to debug on my own has helped a ton. One, because you're able to power through problems and figure out what's really going down. Two, because of the great confidence boost that comes from finding a problem in code and fixing it yourself.

Letters to a Young Developer

This was just part one of a series called "Letters to a Young Developer" where I'll share the great advice I got, or the advice I wish I'd gotten when I first started learning Ruby. Maybe these posts will be helpful to someone, but if not I'll at least have a good log of my experiences.

Read the whole story
treyhunner
3342 days ago
reply
San Diego, CA
Share this story
Delete
Next Page of Stories