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.