My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.
Showing posts with label quality. Show all posts
Showing posts with label quality. Show all posts

Wednesday, September 28, 2011

RIA VS OS

... have you ever thought about it ? I did few times in my 11+ years of RIA centric career!
Even if it's like comparing potatoes with tomatoes I'd like to share my thoughts about it, would you mind ?

What we always laughed about OS


  • the blue/gray screen with an incomprehensible error message

  • the Message Box with some rant about some memory address failure

  • the unresponsive OS due some broken application able to make everything else stuck regardless the number of CPU and thread the OS can handle

  • the "quit program" explicit action that does not quit the program

  • any sort of security issue

  • the change/update that requires a system reboot



What we are always "scared about" online


  • the white screen due some JS/CSS failure for the current browser

  • the forgotten alert or console.log inside some try catch with some rant about generic error message (or even worst, the unmanaged error)

  • the unresponsive DOM/web page due some broken piece of JavaScript able to make everything else stuck regardless the number of CPU and WebWorkers the Browser can handle

  • the "close window/tab" explicit action that takes ages due some greedy onunload operation

  • any sort of security issue

  • the change/update that requires a page reload



We are all in the same field

Architecture matters, experience matters, performances matter, investigations matter, code quality matter, unit tests matter, UX is essential, and UI only attractive.
This is the software development world, no matters which language, no matters which customer, no matters which company ... isn't it? So why things keep being the same in every software field ?

Delivery, delivery, delivery !

The main reason many applications out there, web or not, will rarely be that good.
The scrum purpose is to make theoretically well organized baby steps and the agile often utopia due constant, drastic, changes you may want to face during an already planned task while you are implementing the task itself.
The time ? The worst enemy when it comes to quality. As I wrote in September 2009 we are loosing software quality due temporary solutions that last forever, decisions made without real world use cases to consider and everything else web developers are complaining, as example, about W3C decisions.
Is W3C that bad ? I think it's great, and I think we should all appreciate the Open Source effort we can read, support, or comment, on daily basis as is for JavaScript future if you are tough enough to face people proud by default about their decisions ... they can understand, they can change their mind.

The direction ?

Too much new stuff in too short time that could imply future problems when it comes to maintainability and backward compatibility, the day somebody will realize: "something went terribly wrong here!"
The legacy code that blocks improvements, the country or corporates stuck behind old, deprecated, un-secure, old pseudo standard that are causing them more damage than saving.
Is everything going to produce cheap with screwed up quality? Well, this is apparently the tendency about clothes, cars, and something I always wondered about: if your Master/Phd is from the most expensive and qualified institute in this world, how would you feel to work underpaid in some emerging country able to provide everything you have been instructed for in 1/10 of your salary and with much higher units per months ?
Either that institute won't be worth it anymore, or you gonna feel like everything you learned did not really make sense.
This is a potential side effect of out sourcing too, the cheap alternative to a problem that many times is not truly solved, simply delegated and delivered with lower quality but respecting, most of the time, the deadline that once published will make max 70% of customers happy, loosing 30% until they'll face same problems with next "brand" they decide to follow.

Dedicated to

All those persons out there that do their best in daily basis believing in their job, whatever it is.
All those persons underpaid still able to put best effort and provide results regardless the country/economy situation.
All those workers that would like to have more time to do things better, and all those Open Sources/Standards Maker that should be more distant from this frenetic delivery concept, and a bit more focused on doing things properly and able to last much longer ... we would not need so many changes, software speaking, if things were already great and this is what I have always tried to do with all my old projects, often forgotten, still working after 5 or more years of untouched code, and under newer versions of the same programming language.
I had more time back at that time, and things are still working.
I am missing products like the original Vespa, out of Italian company that can still run in your city street and with 30 years on its shoulder: can your cheap scooter, software, architectural decision, do the same?

Tuesday, February 16, 2010

JSLint: The Bad Part

Every programming language has somehow defined its own standard to write code. To be honest, as long as code is readable, clear, and indented when and if necessary, I think we do not need so many "code style guides" and, even worst, sometimes these "code standards" let us learn less about the programming language itself, helping if we are beginners, sometimes simply annoying if we are professionals.

Disclaimer

This post aim is absolutely not the one to blame one of my favorite JS gurus, this post is to inform developers about more possibilities against imperfect automation we'll probably always find in whatever excellent spec we are dealing with. This post is about flexibility and nothing else!

JSLint And Code Quality

Wehn Mr D says something, Mr D is 99.9% right about what he is saying ... he clearly represents what we can define a Guru without maybe or perhaps but he, as everybody else here, is still a programmer, and we all know that every programmer has its own style if we go down into details.
Mr D programming style has been historically summarized in this Code Conventions for the JavaScript Programming Language page.
All those practices are basically what we can find out about our code using a well known and widely adopted parser: JSLint, The JavaScript Code Quality Tool.
I write JavaScript and ActionScript (based over the same standard) since about 2001 and generally speaking, as experienced developer, I trust what I meant to do, and rarely what an automation tool supposes to teach me about the language.
This is like studying remembering rules rather than being able to understand them, something surely academical, nothing able to let us explore and discover new or better solutions ... we are stuck in those rules, but are we machines? Are we Mr D code style clones?
This post is about few inconsistent points regarding JavaScript Code Quality, with all due respect for somebody that simply tried to give us hints!

Indentation

The unit of indentation is four spaces. Use of tabs should be avoided because there still is not a standard for the placement of tabstops
While size always matters, since to move 1Gb or 600Mb in a network still makes a big difference, I wonder what's wrong with just two spaces. The monospace font we all use to write code on daily basis is "large enough", and while 2 spaces rather than 4 are extremely easy to spot, 4 spaces are absolutely ambiguous.
How many times we had to check via cursor if some other editor placed a tab rather than 4 spaces there? Ambiguity is something that does not match at all with the concept of Code Quality, am I wrong?
Finally, while everybody in this world has always used innerHTML due its better performances against the DOM, Mr D. tells us that tabs are not defined as a standard ... have we never heard something like de facto standard?
Specially in a unicode based language as JavaScript is, where tabs are indeed replaced by "\t" even in Mr D JSON specs, how can we think about whatever JavaScript IDE or Engine unable to understand tabs? Let's avoid them, but still, at least let's replace them with something that does NOT occupy exactly the same space!

Variable Declarations

All variables should be declared before used. JavaScript does not require this, but doing so makes the program easier to read and makes it easier to detect undeclared variables that may become implied globals.
OK, got the point, minifier or munger will take care about this so it could make sense. Now, everything is fine to me, as long as I don't read the next immediate point:
The var statements should be the first statements in the function body.
... are we serious here?
So, if var declaration is the first thing I should do, why on earth I should spend 10 times my time to write semiclons and var again?

// first thing to do
var a = 1;
var b = 2;
var c = 3;
var d = {};

// AGAINST
var a = 1, b = 2, c = 3,
d = {}
;

Faster to type, easier to read, I can even group blocks of variable declaration to define different types (primitive first, object after, undefined later if necessary) and thanks to indentation, the precedent point, I must be an idiot to do not understand what the hell I wrote. Is it just me?
I prefer to perfectly know the difference between comma and semicolon and these two buttons are in a different place, there is NO WAY I coul dmake a mistake unless I don't know the difference ... but in that case I guess we have another problem, I know nothing about JS!
Furthermore, something kinda hilarious to me:
Implied global variables should never be used.
OK, assuming for whatever reason we don't consider global functions references/variables, we should forget:
  • undefined
  • window
  • navigator
  • document
  • Math
  • jQuery (dollar $ is global baby!)
  • everything else that supposed to be reached on the global scope
I may have misunderstood this point so I do hope for some clarification, but again, the difference between a local scoped variable and a global one should be clear to everybody since JSLint cannot solve anything, and I'll show you later.

Function Declarations

I agree lmost everything about this chapter, but there are surely a couple of inconsistencies here as well.
There should be no space between the name of a function and the ( (left parenthesis) of its parameter list. There should be one space between the ) (right parenthesis) and the { (left curly brace) that begins the statement body.
...
If a function literal is anonymous, there should be one space between the word function and the ( (left parenthesis). If the space is omited, then it can appear that the function's name is function, which is an incorrect reading.
Let me guess: if there is a name, there must be a space to identify the name, if there is no name, the must a space as well? A function called function which is a reserved word?
I am sure Mr D has much more experience than me, but I wonder if that guy that wrote function function() {} has been fired, is in the Daily WTF website, it is part of the shenanigans group, or if it is still working beside Mr D ... in few words, how can be no space and a bracket ambiguous?

var f = function(){};
I want to honestly know who is that programmer able to confuse above code ... please write a comment with your name and your company, I will send you a Congratulation You Are Doing Wrong card ... I'll pay for it!!!
Same is for the space after the right parenthesis, as if an argument could accept brackets so that we could be confused about the beginning of the function body, isn't it?
Some bad code there in this chapter as well, which let me think truly weird stuff:

walkTheDOM(document.body, function (node) {
var a; // array of class names
var c = node.className; // the node's classname
var i; // loop counter results.
if (c) {
a = c.split(' ');
for (i = 0; i < a.length; i += 1) {
...

So we have to declare every variable at the beginning, included variable used for loops, the i, so the day engines will implement a let statement we'll have to rewrite the whole application?

var collection = (function () {
var keys = [], values = [];

return {
....

wait a second, consistency anybody? How come the next paragraph uses a natural assignment as that one while the Code Quality is to do not use it?

Names

Names should be formed from the 26 upper and lower case letters (A .. Z, a .. z), the 10 digits (0 .. 9), and _ (underbar). Avoid use of international characters because they may not read well or be understood everywhere. Do not use $ (dollar sign) or \ (backslash) in names.
I am not sure if Prototype and jQuery guys shouted something like: epic fail but I kinda laughed when I read it. It must be said that these practices are older than recent framework, and this is why I have talked about do not explore code potentials at the beginning of this post.
Do not use _ (underbar) as the first character of a name. It is sometimes used to indicate privacy, but it does not actually provide privacy. If privacy is important, use the forms that provide private members. Avoid conventions that demonstrate a lack of competence.
So if I got it right, if we identify private variables inside a closure, where these variable actualy are private, we should not identify them as private so we can mess up with arguments, local public variables (remember cached vars?) and everything else ... ambiguous!

Statements

Labels
Statement labels are optional. Only these statements should be labeled: while, do, for, switch.
...
continue Statement
Avoid use of the continue statement. It tends to obscure the control flow of the function.

Labels are fine, continue, which is basically an implicit label similar to goto: nextloopstep should be avoided. But as far as I read the return statement able to break whatever function in whatever point has no hints about being only at the end of the function bosy as is for ANSI-C programmers?

Block Scope

In JavaScript blocks do not have scope. Only functions have scope. Do not use blocks except as required by the compound statements.

with (document) {
body.innerHTML = "is this a scope?";
}
Never mind, somebody in ES5 strict specs decided that with statement is dangerous ...

=== and !== Operators.

It is almost always better to use the === and !== operators. The == and != operators do type coercion. In particular, do not use == to compare against falsy values.
This is the most annoying point ever. As a JavaScript developer, I suppose to perfectly know the difference between == and ===. It's like asking PHP or Ruby people to avoid usage of single quoted strings because double quoted are all they need ... does it make any sense?

// thanks lord null is falsy as undefined is
null == undefined; // true
null == false; // false
null == 0; // false
null == ""; // false
null == []; // false
null === null; // true, this is not NaN

In few words, as I have said already before, null is == only with null and undefined, which means we can avoid completely redundant code such:

// Mr D way
if (v !== null && v !== undefined) {
// v is not null neither undefined
}

// thanks JavaScript
if (v != null) {
// v is not null neither undefined
}

Moreover, since undefined is a variable it can be redefined somewhere else so that the second check could easily fail ... and where is security in this case?

// somewhere else ..
undefined = {what:ever};


// Mr D way
if (v !== null && v !== undefined) {
// this is never gonna happen AS EXPECTED
}

Please Mr D whatever you think about this post, think more about that silly warning in JSLint: it's TOO ANNOYING!!!
One last example about ==, the only way to implicitly call a valueOf if redefined:

if ({valueOf: function(){return !this.falsy;}} == true) {
// hooray, we have more power to deal with!
}


eval is Evil

The eval function is the most misused feature of JavaScript. Avoid it.
eval has aliases. Do not use the Function constructor. Do not pass strings to setTimeout or setInterval.

aliases? It seems to me that eval is misunderstood as well since there is no alias fr eval. This function may be evil specially because it is able to bring the current scope inside the evaluated string.
Function and setWhaatever do not suffer this problem, these global function always ignore external scope.
Moreover, it is thanks to Function that we can create ad-hoc, runtime, extremely performer functions thanks to dynamic access to static resolution:

function createKickAssPerformancesCallback(objname, case, stuff, other) {
return Function(objname, "return " + [objname, case, stuff, other].join("."));
}

Where exactly is the eval here and why we should avoid such powerful feature when we are doing everything correct?

Unit Test IS The Solution

If we think we are safe because of JSLint we are wrong. If we think we cannot do mistakes because of JSLint we are again wrong. JSLint could help, as long as we understand every single warning or error and we are able to ignore them, otherwise it won't make our code any better, neither more performance killer, surely not safe.
There are so many checks in JSLint that somebody could simply rely in this tool and nothing else and this, for the last time, is wrong!
Next part of the post is about a couple of examples, please feel free to ask more or comment if something is not clear, thanks.

JSLint: The Bad Part

All these tests are about possibly correct warnings, often useless on daily basis code. Please note all codes have been tested via The Good Parts options and without them.

Conditional Expressions

I twitted few days ago about this gotcha. An expression to me does not necessary require brackets, specially it does not require brackets when it is already inside brackets.

"use strict";
var lastValidArgument;
function A(b) {
// I mean it!!!
if (lastValidArgument = b) {
return "OK";
}
}

Somebody told me that if we put extra brackets, as JSLint suggests, it measn that we meant that assignment, rather than a possible missed equal.
First of all, if == is discouraged in favor of === how can be possible developer forgot to press the bloody equal sign three times? It does not matter, the inconsistency here is that if I properly compare there two variables leaving there brackets, theoretically there to let me understand I am doing an assignment rather than comparing vars, nothing happens:

"use strict";
var lastValidArgument;
function A(b) {
if ((lastValidArgument === b)) {
return "OK";
}
}

I would have expected a warning such: Doode, what the hell are you doing here? You have superflous brackets around! ... nothing, inconsistent in both cases, imho.

Unused variable

A proper syntax analyzer is truly able to understand if inside a whole scope, we used a variable as we meant to do. Unfortunately, here we have a totally useless warning/error about an extremely silly, but possible, operation. To avoid the error:

"use strict";
(function () {
var u;
// we forgot to assign the "u" var
// how can this if remove such error from this scope?
if (u) {
}
}());

Agreed, u has been used, but why on earth I have no warnings about a completely pointless if? As far as I understand, variables are truly well monitored ... this requires an improvement ... or remove the Unused variable check since in this case it does not change anything.

Pattern to avoid global scope pollution

The new operator is powerful, but it could be omitted and JSLint knows this pretty well! We, as developers, are able to modify behaviors, using functions duality to understand what's going on. Example:

"use strict";
function A() {
if (!(this instanceof A)) {
return new A();
}
}

// always true
A() instanceof A;
new A() instanceof A;

Cool, isn't it?
Problem at line 7 character 9: Missing 'new' prefix when invoking a constructor.
How nice, thanks JSLint!

Look behind without look forward

More about new, who said this requires parenthesis? As soon as I write new I am obviously trying to create an instance. Since the constructor will be exactely the one referenced after, and since after this operation there will be a semicolon, a comma, a bracket (return without semicolon), how can it be possibly a problem for JavaScript?

var a = new A;

If I don't need arguments, I feel kinda an idiot to specify parenthesis ... maybe it's just my PHP background, isn't it?

class A {}
$a = new A; // OK
$b = 'A';
$a = new $b; // still ok
$a = new $b(); // WTF, $b is a string

// oh wait ...
$b = 'str_repeat';
$b('right', 2); // rightright


Strictly Compared

I have already talked about null and == feature, now let's see how dangerous can be JSLint sugestion:

"use strict";
function pow(num, radix) {
return Math.pow(num, radix === null || radix === undefined ? 2 : radix);
}

// somewhere else, since not only eval is evil
[].sort.call(null)["undefined"] = 123;

Above code will both pass JSLint and always fail the check || radix === undefined since undefined will be 123 primitive.
You know what this mean? Unless we do not define an undefined local scope variable for each function (the most boring coding style ever, imho) we should simply avoid === undefined checks, these are both unsafe, these slow down code execution since undefined is global and requires scope resolution, and these are a waste of bytes

function pow(num, radix) {
return Math.pow(num, radix == null ? 2 : radix);
}

That's it, there is no value that could mess up that check: undefined, null, or a number, 0 included!

Nothing bad in this code

This is the best way I know to create a singleton, or a prototype, to have a private scope as well, shadowing the runtime constructor:

"use strict";
var Singleton = new function () {
// private function (or method)
function _setValue(value) {
// lots of stuff here
_value = value;
}
var _value;
this.get = function () {
return _value;
};
this.set = function (value) {
if (!_value) {
_setValue(value);
}
};
this.constructor = Object;
};

Here we have a Jackpot:
Error:
Problem at line 4 character 14: Unexpected dangling '_' in '_setValue'.
Problem at line 6 character 9: Unexpected dangling '_' in '_value'.
Problem at line 6 character 9: '_value' is not defined.
Problem at line 8 character 9: Unexpected dangling '_' in '_value'.
Problem at line 10 character 16: Unexpected dangling '_' in '_value'.
Problem at line 13 character 14: Unexpected dangling '_' in '_value'.
Problem at line 14 character 13: Unexpected dangling '_' in '_setValue'.
Problem at line 2 character 17: Weird construction. Delete 'new'.
Problem at line 18 character 2: Missing '()' invoking a constructor.

We can nullify the Singleton variable itself, but still nobody else can have access to that scope. This is what I call a variable or method private, and I mean it!
Underscore is perfect as first character, since it helps us to understand a "protected method/property", which is never truly protected, and a real private method/property, shared across instances if it's a variable, usable as private method if called via a public one.
The best one ever, in any ase is:Weird construction. Delete 'new'. ... Weird what? A lambda based language cannot create runtime via lambdas instances?

Conclusion

I hope this post will help both Mr D. and developers, the first guru to improve JSLint syntax checks, while latter people to understand errors, being able sometimes to completely ignore them.
I am looking forward for some feedback or, even better, something I did not consider or some example able to demonstrate or underline my points, thanks for reading.

Thursday, September 24, 2009

Software Quality - We Are Loosing It

This may sounds silly, surely not technical, but today I've lived the last drop before crackpots!

IE6 Inside The Cash Point

I am not joking, I have no idea how many cash points use windows and IE to run a 7 screens software. Have you never noticed a "click clack" while you are performing your operations?
OK, maybe banks do not even buy Microsoft licenses, or maybe those are dedicated cache machine version of Windows, but I could never imagine to find a windows popup with an error in a cache machine, it is ridiculous!
Those one with just text? Well, they look old and ugly, but I've rarely seen one disabled.
We have dozen of valid Operating System able to perform the same software for years without requiring a single reboot. How difficult will be to create an OS specific for a cash point where operations are always the same, adding just 1 image format supported? What I mean is that you can find active screens with lottery ads inside running 24/7 without problems over a hilarious hardware.
Take one of them, add 20 buttons function, that's all we need to click: £10 and digit few numbers, isn't it?

The Hub 2.0 Router Firmware Disaster

I am having constant problems with my ADSL since the first day. First of all the company wrote in the website that for first 10 days I could have noticed disservice but after everything would have been fine. So far, so cool, I was freaking out thinking "OMG, my router is alive, it programs itself!!!" ... then I have simply realized that this company is just selling, so once they bring you the router they have a ready excuse if things are not working as expected ... you have already signed, and good luck with assistance 5 days a day, without specific hours, and during the week ... sure, I day off to wait somebody for somethig I am already paying.
Moreover, without touching anything, and monitoring the router directly via its interface, they asked me via phone if I was in Wireless or Cable ... I mean: WHAT? THE ROUTER IS TELLING ME ITS SPEED, I HAVE NOT A NETWORK PROBLEM!!!
It does not matter, I am struggling with 160kbps of bandwidth and apparently, even if for 2 weeks everything was almost fine, now it's my problem ... they need to come here ... to do what?
Checking online the firmware of this router has the worst history ever.
Is it that difficult to develop a firmware or this company just payed the cheapest one "who cares about the software if it works somehow"?
Right, now I have the latest version of one of the most problematic firmware I have ever seen. I was complaining with ASUS and its firmware nightmare where nightmare meant 1 every year and now I have discovered than a much simple device has so many software problem ... OK, cheap router, but they sell it like gold, and crappy software ... that's cool!!! I wonder how many problems there could be in a standard configuration as whatever phone line is. Is too noisy? Cable problems? No, it's the router, but they'll never tell us their router has problem. Most likely they'll let us buy a new PC to discover that the problem was not the PC ... cool!

Supermarket Big Chains With Bugged Self Check Out

Again, I am not joking, in the place where I go almost every day to buy something for lunch I hve never seen all self check out machines active without problems, never!
The hardware is pretty simple though, touch screen with basically 3 big buttons, a barcode reader, and a money counter for the change. Simple, isn't it? It's not, 'cause these machines never work more than 2 consecutive days ... always problems. Well done Big Chain, as summary you paid the cheapest machines, and your are paying 10 times more due to constant problems these machines have. Everybody does its business, right? Today there were 2 3 of us stuck in front of these machines all without notes change ... I mean, the machine counts money, it is never wrong with the change, and it does not understand when it is finished? The money scanner knows there's no money left there, and it tries again, and again, and again ... used software did not think that when it's finished, it's finished, the machine should simply start to flash the top red light with a clear warning: I HAVE NO MORE MONEY
This would make everything more efficient, since I spent 10 minutes in a self check out machine rather than 1 in the human driven one ... cool!


Run To Deliver

Too many competitors, but apparently it's not the same about developers quality. This is true for the web, for microwaves, for every electric stuff ... the hardware does not cost anymore, what we pay is always the software. 20 years ago there was less software but hell if it was working as expected. Nowadays, software development time is too frenetic, there is no time to do a proper analysis, no time to properly structure the code, no time to write decent comments, no time to describes problems, no time for brainstorming, no time to find the best solution, the first that quickly work is fine ... everything is a quick fix, and if it is not and we had time to things properly, we won't have time to create unit tests. Agile, SCRUM, Extreme, these therms are rarely concretely applied over whatever development team but they are fashionable therms, so everybody is Agile today ... We used that OS lib, without showing credits anywhere in our sold application, we have quickly fixed everything without testing, but we have respected the ridiculous deadline 'cause the customer is waiting ... but isn't the customer the one unhappy when things do not work as expected?

AS Summary

We need to slow down, we need to think more, we need to understand why that program worked better, why that library is solving this or that problem and how it is doing it, if we would like to be able to extend it or to customize it. This "1 hour deadline" for everything is visible, touchable, on daily basis with daily software wherever it is ... what is going on? We can't blame always outsourcing though, isn't it?

Tuesday, January 27, 2009

png to gif transformation - an excellent free solution via PHP GD2

Why we still need png to gif in our web pages


There a couple of valid plugins for different libraries able to manage "silently" png transparency in order to fix those browsers (cough: IE6) that are still used, for god knows which reason, but not able to understand properly the alpha channel. The problem is that these plugins cause overhead in our pages and for each png images, which is nearly a non-sense since these plugins fix old browsers whose performances have never been brilliant!
Especially for modern GUIs, where little icons are widely used, these plugins could make the application incredibly slow.
If we could choose old good GIF instead of png, 'till the end of those browsers, the problem will not exist and performances will be acceptable.

PNG 2 GIF, simple? ... not, really!


First of all a couple of search via Google brought me in "free but you have to pay anyway" applications through some open source, simple, but not that nice, program language solution, incompatible with modern interpreters or not able to produce a good quality result.
The problem is basically this one: alpha channel is something amazing, but it changes border colors if we are putting the png over a bright background rather than a dark one.
For this reason it is really difficult to obtain a valid GIF copy of the original PNG feel using common transformers, since the main difference is given by our cool theme that can be bright or dark.
Thanks to PHP and its distributed GD2 library, I have been able to create a good compromise between pixelated borders and our chose theme.

png2gif, the php/gd2 way



function png2gif($pngs, $background = array(255, 255, 255), $dest = 'gif'){
// by WebReflection
foreach($pngs as $png){
$size = getimagesize($png);
$img = imagecreatefrompng($png);
$image = imagecreatetruecolor($width = $size[0], $height = $size[1]);
imagefill($image, 0, 0, $bgcolor = imagecolorallocate($image, $background[0], $background[1], $background[2]));
imagecopyresampled($image, $img, 0, 0, 0, 0, $width, $height, $width, $height);
imagecolortransparent($image, $bgcolor);
imagegif($image, str_ireplace('.png', '.gif', $dest.DIRECTORY_SEPARATOR.basename($png)), 100);
imagedestroy($image);
}
}

// example
png2gif(glob("icons/*.png"));

That's it, you copy and paste an entire directory into, for example, an icons folder, and you call the function passing the list of files contained in that directory.
Parameters are the file list itself, the background color, and finally the destination folder to put transformed png into gif, by default the dir "gif".
The main difference between this function and every other method I found, is that borders are gracefully adapted to your main theme, by default a bright one with white background.
In this way you can choose how borders should be readapted instead of black borders for alpha problems, or cutted one. Even circle icons result are, in my opinion, brilliant!
The array should contain R,G,B integer values, from 0 to 255, where array(0,0,0) is black and array(255,255,255) is white, the default background theme.

You can try this function to convert most common icons theme, and please tell me if the result was not good enough ;-)

P.S. for PHP maniacas, the imagecopyresampled gd2 function has been the only one able to merge properly the png into chose background color ... I don't want to tell you how long did it take to find this kind of solution (passing via pixel by pixel color allocation ... omg!)