Tuesday, October 26, 2010

Ruby

I recently had to learn Ruby, at least, in the form of IronRuby. So far, my experience with it is good. Admittedly at first I thought that it was just another language, but after trying it out, it actually felt good working on it.

I have to point out though, the biggest misconception by the more fanatical supporters of Ruby. Ruby seems to be "agile" language. Thanks to the fantastically successful Basecamp application, Ruby has become the champion of agile software development.

Well, sorry to burst your bubble, but agile is about people over tools. Ruby is just a tool. A good tool, but it's still a tool. Improperly used, it can still result in a horrible project. Bad Ruby code is still bad code. Hell, it may even be worse than bad COBOL code.

At least most of the COBOL code out there, 5 billion or so lines, works.

Tuesday, October 5, 2010

DB or Code

I once had this feature to implement. There was a database table that had a list of user ids, gate ids and dates. The table stores this data so that it can track who passes at which gate. Users who do not use their ids at the gate will be caught.

Anyway, I could put the date calculation logic in one of two components. I could either put it in the database, as a field in a view. I could also put it in a class, as a method.

As much as I'd like to weigh in the pros and cons of both approaches, I don't think I can. I don't have enough experience as an architect, or a database designer to give proper advice. However, I do have this one bright idea.

Put it where the possibility of screwing up is less!

Because I was better at using the date calculation functions of the database than I was at Java (I hadn't discovered joda time yet) , I put it there. It worked out too!

Thursday, September 23, 2010

Morale Failure

I recently had the displeasure of witnessing a developer flee. The man just left, and didn't even bother writing down his password, just in case somebody else needed to work on his computer, or access the files he didn't save in the shared drive.

Now, the man deserves a lot of criticism for what he did. He made his current project even more of a pain than it already is. Still, one has to examine the series of situations that led to his unexpected departure.

He was a designer. He knew a little PHP. Although he's not totally inept, if PHP knowledge translated into physical strength, and he got into a fight with me, I would seriously injure the man.

Then there's the project. It was a Joomla project, involving internationalization. The languages involved were Japanese and English. Let's just say there was a problem with Joomfish. It was looking for table that wasn't in the database.

Now, while he was unprofessional as hell, expecting a newbie developer to work on a body of code as big as JoomFish is well, asking for trouble. It's the modern equivalent of asking some random mythological Greek kid (who does not have a divine parent) to strangle the hydra. Joomla can be problematic for people who actively use it, what more for somebody who has never used it before.


  if (!thisCustomer.IsRegistered)
  {
   decimal totalProduct = decimal.Zero;
   decimal TaxShippingTotal = decimal.Zero;

   //taxes for shipping
   Decimal CountryShippingTaxRate = AppLogic.GetCountryTaxRate(thisCustomer.PrimaryShippingAddress.Country, AppLogic.AppConfigUSInt("ShippingTaxClassID"));
   Decimal ZipShippingTaxRate = AppLogic.ZipTaxRatesTable.GetTaxRate(thisCustomer.PrimaryShippingAddress.Zip, AppLogic.AppConfigUSInt("ShippingTaxClassID"));
   Decimal StateShippingTaxRate = AppLogic.GetStateTaxRate(thisCustomer.PrimaryShippingAddress.State, AppLogic.AppConfigUSInt("ShippingTaxClassID"));

   foreach (CartItem ci in cart.CartItems)
   {
   Decimal StateTaxRate = AppLogic.GetStateTaxRate(thisCustomer.PrimaryShippingAddress.State, ci.TaxClassID);
   Decimal CountryTaxRate = AppLogic.GetCountryTaxRate(thisCustomer.PrimaryShippingAddress.Country, ci.TaxClassID);
   Decimal ZipTaxRate = AppLogic.ZipTaxRatesTable.GetTaxRate(thisCustomer.PrimaryShippingAddress.Zip, ci.TaxClassID);
   Decimal DIDPercent = 0.0M;
   Decimal DiscountedItemPrice = ci.Price * ci.Quantity;
   QuantityDiscount.QuantityDiscountType fixedPriceDID = QuantityDiscount.QuantityDiscountType.Percentage;

   //Handle the quantity discount
   DIDPercent = QuantityDiscount.GetQuantityDiscountTablePercentage(ci.ProductID, ci.Quantity, out fixedPriceDID);
   if (DIDPercent != 0.0M)
   {
    if (fixedPriceDID == QuantityDiscount.QuantityDiscountType.FixedAmount)
    {
    if (Currency.GetDefaultCurrency() == thisCustomer.CurrencySetting)
    {
     DiscountedItemPrice = (ci.Price - DIDPercent) * ci.Quantity;

    }
    else
    {
     DIDPercent = Decimal.Round(Currency.Convert(DIDPercent, Localization.StoreCurrency(), thisCustomer.CurrencySetting), 2, MidpointRounding.AwayFromZero);
     DiscountedItemPrice = (ci.Price - DIDPercent) * ci.Quantity;

    }
    }
    else
    {
    DiscountedItemPrice = ((100.0M - DIDPercent) / 100.0M) * (ci.Price * ci.Quantity);
    }
   }


And this isn't just for Joomla. This is for every framework out there. Yes, such frameworks can save on time, but they make the human resource costlier. The sample above is from aspdotnetstorefront. Imagine being new on the team and then having to add custom logic in that!

Wednesday, September 15, 2010

Bloated Prepackaged Software

In one of my more recent projects, the end client had a bunch of services on a web service. The end client wanted a shop that allows customers to look at the services and buy access. The middle man, our actual client, suggested aspdotnetstorefront.

The project involved multiple tiers. There was the web service, there was the payment gateway, and there was the cart itself. Everything had a price tag of sorts, so I was not able to play around as much as I could have. That alone should have sounded alarms in my head.

See, we were expecting aspdotnetstorefront to save us time. Well, we were wrong. Here's an example.

The date and time of the database server and the HTTP server should be the same. See, aspdotnetstorefront checks the date of the database server and the HTTP server to check for administrative logins. If they are different, it will log the administrator out seconds after he or she logs in.

Now, I would understand if CPanel behaved like that, because CPanel was designed to administer everything from one server, but for a shopping cart system? What, they didn't think customers might have the HTTP server on one state, and the database server on another state? That's just bad design.

Well, I could go on, but I probably won't be able to make a proper review. See, I'm not saying it sucks. Lots of people do, but lots of other people manage to make it work for them. I'll have to interview them all, and I don't want to do that.

I think aspdotnetstorefront behaves like that because it tries to do everything possible. Having lots of options is good, but it can bloat software to the point where it's impossible for consultants to just pick it up and make stuff with it. They need to consult the encyclopedic manual first.

That's why they don't make amphibious cars just yet. It's hard enough making cars safe for the road. Making it safe for lakes, rivers and oceans might turn it into this thing.



Yes, I got that picture from MobyGames. Where else will I find a picture of a level from an optional dungeon in an awesome RPG?

My point is, one has to be willing to put up with the bloat if one plans to use prepackaged software.

Monday, September 6, 2010

The File Uploader

Recently, I had to check on different PHP file uploaders. This one came up.

Directory Listing

Looking at the code, I would have to say that it needs refactoring. While there are a lot of comments, it's nowhere near as clean as it could be. It even uses the old <? PHP tag syntax.

Maybe I should write my own version. I'll make my cleaner.

Yeah, I'll think I'll do that.

Friday, August 27, 2010

Hurry up and DIE, PHP4

I like Wordpress, although I have to admit that it is not perfect. This is one such line that makes it imperfect. On strict servers, these lines cause me grief.

/**
 * PHP4 constructor
 */
function WP_Embed() {
    return $this->__construct();
}

Okay, it's important to keep things backwards compatible. Personally, I enjoy playing old games. When I read about Raymond Chen's work keeping old software compatible with new versions of windows, I can't help but feel respect for the guy.

However, this is different. In my example, a team was working to keep the OS (Windows) compatible with old software (SIMCity). Running old software in a new OS is an added value, and is less likely to introduce security errors. In the case of wordpress, the wordpress team is working to keep new software (Wordpress itself), compatible with an old runtime (PHP 4). Well, being able to run a new version of wordpress in PHP 4 is an added value too, but it becomes a major problem when security errors are left unpatched because support for PHP 4 has stopped.

As of this date, it has been two years since the last update for php 4 was released. I know there are still some applications out there that run on PHP 4. I worked on one last year! When I did, I complained about it, but it wasn't my place to tell the client, so they didn't get all the information about how gnarly PHP 4 is.

Well, not all clients can understand that using an old runtime is bad for their system. However, that does not mean that consultants shouldn't try anyway. Clients can be hardheaded, but I think that even the most technophobic Luddite will appreciate being told everything about their system. Giving clients the all the information that they need to make a decision about their investment should be the goal of every consultant.

At the very least, it's going to be their fault if stuff breaks, and there isn't an update to fix the problem. Getting clients to stop using this undead version is the fastest way to get rid of it.

Saturday, August 21, 2010

What the Hell File Naming

A long time ago, my mentor saw me putting multiple classes in a single C# file. He hit my head, and told me that I was doing something very wrong. He said that files should have just one class so it's easy to find out where something went wrong. Well, he was correct. It's easier to find an error in 1000 files with unique names, compared to scrolling down one gigantic file with the Ctrl+F hotkey.

That way way back in 2004.

Now, I find myself in the same situation. Being a freelance developer, I found myself working on a PHP framework called PHP Road. Now, before anybody googles it, I will warn everybody that it doesn't exist by itself. It apparently became part of the Lemonstand shopping cart platform.

I don't really have anything against it, but somebody who used the PHP Road framework named their files this way.

signupp.php
singuppt.php
signupt.php

Well, apparently, each file did something unique, and each file was important. Care to guess what? Sure, they all had something to do with signing up, but aside from that, what do they do?

Well, it's not easy to guess. Also, guessing takes time. Writing get_included_files() and looking at the source takes time.

I just had to add * REQUIRED to a few input boxes, and I had to check which files were included with PHP code. It shouldn't be that way. Well, that means that files need to be renamed.

It's okay to put some secret code in your file names, but at least make sure it's easy to decipher. Remember, somebody else might be working the code in the future. They also might be strong enough to curb stomp people.

Friday, August 13, 2010

Basic TDD in PHP

TDD can be best decribed as writing code that tests other code first. At first, it sounds like a really confusing concept. How does one write code that tests other code? Well, one has to follow two simple rules.

1. The test must be simple. A complicated test needs another test to prove that it works. This spirals into infinity, like a fractal of doom. Alien geometries, anyone?

2. The test must be written first. Because one already knows what the function will do, it's easy to test for it.

Given that, let give a real world example from one of my recent projects.

My client wanted to save the educational attainments of people. There is a database with five columns.

ID - School - Start Year - End Year - Description

The ID column automatically increments, and the Description column is optional. Everything else is required.

My client wants a function to do this. All the data is in the $_POST array. The function will return "Success!" if the information was saved. However, if there is a problem, it will output an error message.

This is what the code file looked like at the start.

function tryToSaveEducation($data) {
    return 'Success!';
}

$isTest = array_key_exists('test', $_GET) ?
    'true' === $_GET['test'] : false;
if($isTest)
{
    # Tests go here
    assert('No data' === tryToSaveEducation(null));
}

I shall call this file, TryToSaveEducation.php. Naturally, by navigating to localhost/TryToSaveEducation.php?test=true I can test the method.

On the first run, it's going to fail. There is no if statement that checks for null parameters. Thus, I will modify the function accordingly.

function tryToSaveEducation($data) {
    if(is_null($data))
        return 'No data';
     
    return 'Success!';
}

Now I just made the test pass!

Now, this might seem like a bad example because the feature I'm testing is a simple null parameter validation. However, remember all the columns that I listed earlier? I'll have to add validation for those columns too! Of course I'm not going to write them all down here. Anyway, now I can check if the function catches a null parameter in one simple action, even if I add 100000 lines of code.

Speaking of code, this is especially useful in large projects that do many different things. Being able to run tests quickly can save a team a lot of time.

Well, maybe I should write about PHPUnit next.

Thursday, August 5, 2010

Conditions from Hell

Here's a good example of refactoring.


if ((($_FILES["file"]["type"][$n] == "image/gif")
|| ($_FILES["file"]["type"][$n] == "image/jpeg")
|| ($_FILES["file"]["type"][$n] == "image/png")
|| ($_FILES["file"]["type"][$n] == "image/pjpeg"))
&& ($_FILES["file"]["size"][$n] < 200000)) {
}


Look how complicated the whole thing is! To think the pseudocode behind it was a simple "make sure the file is a picture and it is a smaller than 200000."

It's easy to refactor though.


$isGif = "image/gif" == $_FILES["file"]["type"][$n];
$isJpg = "image/jpeg" == $_FILES["file"]["type"][$n];
$isPng = "image/png" == $_FILES["file"]["type"][$n];
$isPjpg = "image/pjpeg" == $_FILES["file"]["type"][$n];
$isPic = $isGif || $isJpg || $isPng || $isPjpg;

$smallEnough = 200000 > $_FILES["file"]["size"][$n]

if ($isPic && $smallEnough)
{
}


Sure, there are more temporary variables, but it's easier to read. That will save more time when somebody new picks up the code.

Tuesday, July 27, 2010

The Unholy Trinity

Hi, and welcome to another post about how much x or y sucks. Well, not really. This is more of a "lots of people who use x and y" sucks type of post. Whatever the programming language, or framework, or CMS, there will be people who make it work, and like it.

Well, this post is about Javascript, HTML, and PHP. All three are established technologies that make life a little bit easier for everybody. Well, except Luddites and people with no access to the Internet. All three of these technologies work.

Now, because they work, an entire industry has evolved out of making money from it. I myself make money out of fixing websites. While this financial reward is a good incentive to learn, it is not a good enough incentive for many people to learn enough. There is so much money being made off the Internet that it attracts people who suck at writing code.

I was never a computer scientist, but I think some of them believe that the golden age of information technology came when computers were giant, vacuum tube monsters that scared the common person away. Programming back then usually involved a lot of numbers. Despite the tedium of it all, they consider it the golden age because only the most disciplined and learned people actually handled computers. Except for the rare, insect induced error, most problems resulted from mistakes by people they knew, people they could talk to, and people they can expect to fix the problem.

Nowadays, with high level languages, writing a program is considerably easier. In fact, it's so easy that thousands of people join the big happy family that is the IT industry yearly. Just like any family, there smart relatives, and stupid relatives.

It's possible to write bad code even with a ridiculously strict language like ADA or Eiffel. Javascript, HTML, and PHP are not unique in that regard. However, Javascript, HTML, and PHP are so damn easy to learn, that any fool can pick up a book, code a little, and then pass off as a pro.

Take HTML for example. It's fantastically hard to write it wrong. However, I've handled pages where the design is scattered all over the elements, and design changes take hours! Learn CSS!

As for Javascript, there are still quite a few people who haven't caught on to the JQuery, MooTools bandwagon. Stop writing your own code, and then complaining why it doesn't work on every browser!

However, PHP, at least for me, is one of the worst offenders. I've seen boatloads of code that don't even have proper indentation. Sure, the code words, but when something needs to change, it takes forever to understand it, let alone change it.

Well, it's not the fault of tool. It's the fault of all the people who don't use it properly.

Tuesday, July 20, 2010

What Makes Joomla so Hard?

I recently had to work on a Joomla project. It was a simple application. There was at most 20 pages, and hardly anything was generated dynamically. It could have been a simple HTML website that anybody with a basic knowledge of HTML could edit.

However, because it was the year 2010, somebody made the decision to use a content management system, in this case Joomla. The goal of using Joomla was to free the unlucky soul tasked with maintaining the site the burden of learning HTML. Things didn't turn out that way though.

The development didn't really have a process. They wanted results now, so we used the first modules and components that could recreate the mock-up. While this rapid development seemed like a boon, little did we know that there was a price to pay.

In the last weeks, the clients asked for SEO friendly URLs. Let's just say that Joomla does not do this by default. We turned on the built-in SEO friendly URL feature, but it was not SEO friendly enough. We then tried installing components like Artio JOOMSEF and it apparently didn't like the configuration of the server.

Well, the development slowed down, and lots of things got finished late.

Now, I'm tempted to say "JOOMLA SUCKS BIG TIME" because a lot of Joomla fanboys will frequent this post and shoot my hit count up but I won't be giving credit where credit is due. Joomla is a tool, just like C++. It can make life easier, or harder depending on the usage. In this instance, it made life harder because we neglected to think about a few problems.

1.) Modules and components don't always work well with each other. In a perfect world, people write code that only affects itself. The world is not perfect and there are thousands of bad programmers out there, and some of them write for Joomla. Test everything.

2.) Manage the expectations of the client. Sure Joomla is as customizable as any ground up website, but it will most likely take more time. Modules and components can be altered to produce all sorts of effects but making a module or component do something it never did in the first place increases the time it takes to test things, and exposes the project to the first problem.

3.) Get the client to focus on things that are really important. In the above example, the client was paying too much attention on font sizes and button sizes. Sure, it was easy to change stuff like that, but it created an illusion that the project was actually close to completion. When the really important stuff like SEO friendly URLs came out, things got delayed and we got the flak.

People make things hard. I could be using an archaic language like COBOL, but if I coordinate with my clients better than the above example, I'm sure I'll have an easier time.

Wednesday, July 14, 2010

Hello World

It's normally a custom for new programmers to write a "hello world" program. Underlying the seemingly simple command that displays two words is a vast set of instructions that can turn a mere mortal (in the real world) into a deity (in the computer world). With all that power, wouldn't it be cool to just jump into the the computer realm like in Tron or in Superhuman Samurai Syber-Squad? Although it sounds good, any technological paradise could easily turn into technological Tartarus, considering that a lot of people can't use computers properly.

I'd like to introduce Edsger W. Dijkstra. He's a well known computer scientist from the Netherlands. Here is one of his quotes.

How do we convince people that in programming simplicity and clarity —in short: what mathematicians call "elegance"— are not a dispensable luxury, but a crucial matter that decides between success and failure?

Now, this quote is extremely relevant to the point of making it my first post because too many people in Information Technology are making their lives more complex. To prove my point, here is a math example.

I start at the number 10. I want to be at number 2.

10 - 8 = 2
10 + (10 - 18) = 2
10 * (2 / 10) = 2

Needless to say, there are are infinite number of possibilities. Now, given that I just wanted the number 2, the first option is better. Why waste time calculating more and more numbers when a simple equation can do the trick?

Now, it's tempting to think that people always pick the simplest equation, the easiest path, but that isn't really the case all the time. Take for example, Joomla. It's a content management system, and a popular one to boot. Lots of users are using it, and lots of developers are writing code for it. It's also open source, so users are free to alter the code if they need to. The problem though, is that a lot of the code for Joomla sucks. I've been tasked to alter modules and plugins to make it behave in a certain way, and most of the time, I keep seeing code like this.


if($variable1 == $class1->method1($parameter1, $parameter2, $parameter3, $class2->method1()) || ($variable2 && $class1->method2($parameter4, $parameter5)))


I'm not saying that Joomla sucks, or all of its developers sucks. I'm just saying that some people just write stuff and make it the problem of somebody else. I just used Joomla as an example because the more popular something is, the more crap gets thrown in its direction, from all directions!

Take the IPhone for example. I hear it's really popular, despite having a bad antenna that can't receive signals through human flesh. It's selling like pancakes. Now, the application market for the IPhone is booming. Now for every useful application, or nifty new game, there's this horrible app waiting to be purchased. In truth, there are enough bad applications that Apple has to resort to draconian licensing with the SDK.

Generally, I all for the spread of technology. I think it can really help people do more with their lives. However, when some fool starts misusing technology, making things harder for other people, that's when the hammer needs to be brought down.