PSR-2 Coding Style Guide

phpThe PSR-2 Coding Style Guide is an extension of PSR-1, which I reviewed in my last post.  The PSR standards were created and agreed to by a diverse group of PHP framework and library developers, so that all frameworks and libraries will be able to be used together with the same syntax.

PSR-1 laid out basically three naming conventions: 1. Classes should be named using StudlyCaps or upper Camel case, like so: class BlueMoon{}, 2. methods in the classes should be named in lower camel case, like so: public function setTime(), and 3. constants should be named with caps in snake case, like so: const VERSION_NUMBER =.

Let's expand this with PSR-2 which delves into how to style PHP code. This standard has been much needed to make all code easier to read and understand, and to let PHP developers know how their code should be styled. Here we go:

1. INDENT - Indent 4 spaces, not tabs.  The problem with tabs is when you go from developer to developer, tabs are different, and the code doesn't line up properly.  In most modern IDEs, you can set tabs to convert to spaces automatically. The 4 spaces is curious, since I've mostly used 3, but from my perspective I'm glad we finally put a stake in the ground.

2. LINE LENGTH - No hard limit on line length, the soft limit is 120 characters, however you should try to keep your lines under 80 characters for easier reading.  Don't leave a blank space at the end of the line after the semicolon, and of course, only one statement per line.

3. NAMESPACE - Use one blank line after a namespace declaration, and a blank line after a single or group of USE declarations.  The namespace must be the first line in the file after the PHP tag.  This makes developers more easily aware that the code is within a particular namespace or is using a particular alias for that namespace.  Here's an example:

namespace Vendor\Package;

use PrintInterface;
use TextClass as TC;
use Vendor2\ORM3\OrmHandler;

class SetUpPrint extends TC implements PrintInterface
{
    ...Do something
}

4. CLASS - Opening braces for classes MUST go on the next line, and the closing brace must be on a line of its own at the end.   YEA!, I've been fighting Kerrigan for years, and since I code this way, I'm a happy camper.  After the closing brace of the class leave one blank line.

The class keyword should be in lower case.

Extends and implements keywords must be declared on the same line as the class.  If there is a list of implements you can put them each on a line below the class indented.

Omit the closing PHP tag if the file contains all PHP code.  This one has tripped up many a developer with blank lines after the closing PHP tag throwing an error.

Here's two examples:

class SetUpPrint extends TC implements PrintInterface
{
    ...Do something
}

class SetUpPrint extends TextClass implements
    \PrintInterface
    \FontInterface
    \Internationlization
{
    ... Do something
}

5. METHOD - Opening braces for methods must go on the next line, and a separate line for the closing brace. Yea! again.

Parenthesis should butt up against the method name with no spaces, and there should be not be a space after the open parenthesis or before the closing parenthesis.

Visibility or scope, like public, protected, and private must be declared on all methods.  The order of declaration should be abstract and final, visibility, and last static before the function keyword.

Method names must not start with an _ .  This can cause some confusion with __contruct type or other PHP magic constants.

Method arguments: commas should have a space after the comma, but none before the comma.  Arguments can be put on multiple lines but they must be indented. If multiple lines are used for arguments, the opening parenthesis is on the method line, and closing parenthesis and the opening method brace are on the same line.

Here's the example:

class SetUpPrint extends TC implements PrintInterface
{
    final public static function cannedText($arg1, $arg2, $arg3)
    {
        private $count = 0;
        public  $team_id = null;

        ... Do something
    }

    private function calculateRate(
        $arg1,
        $arg2,
        $arg3
    ) {

        ... Do Something

    }
}

The second method is harder to read, but every once and awhile is needed.

6. CLOSURE - For the most part closures have the same styling as methods with these differences:

Closures must have a space after the function keyword.

When used with the use keyword, there should be a space before and after the use keyword.

Here's the example:

$closureRouting = function ($arg1, $arg2) {
    ... Do something
};

$closureRouting2 = function () use ($var1, $var2) {
    ... Do something
};

7. PROPERTY - Declare a visibility on all properties.

Never use the var keyword, this is used with  JavaScript and would cause some confusion.

Use one property per statement instead of chaining properties on one line.

No underscores before the property name, like $_income, instead use $income.  The underscore was used in some frameworks and can be confused with PHP magic variables.

Not this:

    private $count = $_items = 0;
    public  $_guide_id = $team_id = '';

Instead, like this:

    private $count = 0;
    private $items = 0;
    public  $guide_id = null;
    public  $team_id = '';

6. CONTROL - Control structures, like IF, WHICH, FOR, and FOREACH must have one space before the condition parenthesis.

The parenthesis should not have a space after the opening parenthesis or a space before the closing parenthesis.

The opening brace should have one space after the closing parenthesis and go on the same line, oh well I can't win them all.

The structured body should be indented.

The closing brace should have a line of its own.

Here are some examples of several control structures:

if ($i == 1) {
    Do something;
} elseif ($i == 2) {
    Do something else;
else {
    Do a third thing;
{

for ($i = 0; $i < 10, $i++) {
    ... Do something;
}

foreach ($condition as $key => $value) {
    ... Do something
}

try {
    ...Do something, and throw some errors
} catch    (firstError $e) {
    ... Do something with the error
} catch (secondError $e) {
    ... Do something else with an error
}

8. SWITCH - The case keywords should be indented from the switch keyword. There should be a line between each case block with the exception of the first case.

Inside the case, the break keyword should be indented with the rest of the code in the case body.

There must be a comment, such as "// No break" when a fall-through is intentional in a non-empty case, like so:

switch ($condition) {
    case 0:
        echo 'The condition is 0';
        break;

    case 1:
        echo 'The condition is 1. ';
        // No break

    case 2:

    case 3:

    case 4:
        echo 'The condition has been set';
        return;

    default:
        echo 'No condition was set';
        break;
}

9. KEYWORD - Here's one that I'm guilty of.  Keywords, like true, false, and null show be in lower case.  I've always put them in upper case for visibility, not anymore.  They should be set up like so:

if ($turn == true) {
    Do something;
} elseif ($turn == false) {
    Do something else;
else {
    Do a third thing;
{

That's it for PSR-2.  It is interesting to note that this style guide isn't just one developer's view of the world, which has been the problem with all the other style guides. The way this standard was developed was to poll all the members of FIG as to each coding style to determine the preference of a majority of the members, considering that the members of FIG cover a broad spectrum of PHP development, these coding styles should be considered not only a standard, but what the PHP community wants to see when reading code.  Thus a developer should strive to code with this style, knowing it is what other developers are expecting.  Thus a standard is born.

As an aside, in both NetBeans and Eclipse you can set up this style in the editor, and then hit a key sequence, and your selected code will be formatted to this style, nice.

To configure the format in NetBeans, go to Tools->Options->Editor->Formatting. You can set the indents for all languages. To set the rest of the style, click the PHP drop down under "Language:" and then in "Category:" drop down you can set the rest of the styles. Once formatting is set in NetBeans, all you have to do is select the code you want to format, and do an Alt-Shift-F and presto your code is formatted. I find I use this a lot while coding to keep my code looking good.

Posted in Naming Standards | Leave a comment

PSR-1 Basic Coding Standard

phpWith the explosion in PHP frameworks and PHP libraries that has occurred over the last couple of years, developers have started to be concerned about standards for coding that can be used across all frameworks.  To this end, at the php|tek conference in 2009, a group was established called, the PHP Standards Group, which later became the "Framework Interoperability Group", or FIG.

FIG members include many of the most popular frameworks and libraries, like: Zend, Symfony, Lithium, Laravel, PEAR, Composer, phpDocumentor, Drupal, Joomla, Propel, and Doctrine to name a few.  You get the idea.  Each of these frameworks and libraries had their own code, and developers wanted to make sure it all played well together.

To date, FIG members have agreed on four standards that they have labeled PSR-0 to PSR-3.      PSR-0 is an Autoloading Standard, PSR-1 is a Basic Coding Standard, PSR-2 is a Coding Style Guide, and PSR-3 is a Logger Interface, which sets up a Syslog protocol.

The FIG group is gradually becoming a major force in PHP that will dictate how all PHP developers should code for interoperability, thus it behooves all PHP devleopers to pay attention to and code using the PSR standards.  With that in mind, I thought it would be worth while to gradually review these standards.

We'll start with PSR-1 the Basic Coding Standard.  This standard is meant to be a minimum requirement for interoperability between frameworks, so it is relatively short.

1. Only use <?php ?> and <?=  ?> starting and ending tags, and not any other variations.
To avoid interoperability problems in the past frameworks and libraries had been making different starting tags, this avoids the problem.

2. Only use UTF-8 with out any BOM, or byte-order-marking.
The Unicode standard permits byte-order-marking with UTF-8.  Its purpose was to signal the start of the text string with the proper encoding.   One of the main reasons for BOM was legacy encoding, and one of the major drawbacks was it can interfere with pattern matching.  For interoperability, it is best to ensure no BOM is used, and to standardize on UTF-8.  It  means not having to worry about different encoding across frameworks.

3. Namespaces and Classes must follow the PSR-0 standard.
This is for ease of autoloading. We'll cover this in a post on PSR-0. Mostly it means each class is in a file by itself and has a namespace.

4. Class names must be declared in StudlyCaps.
There are two base naming conventions, Snake_Case, and camelCase.  Snake case connects words with underscores, like so: mail_label, or Mail_Label.  CamelCase separates words with capital letters.  CamelCase comes in two forms lower camel case, called camelCase, and upper camel case, or StudlyCaps.  The upper and lower refer to the first letter of the name, thus class names should not be : class codeGenerator, and instead should be: class CodeGenerator with the first letter capitalized.

5. Method names must be declared in camelCase, like: public function getFirstName();

6. Class constants must be declared in all upper case with an underscore separator when needed, like so: const VERSION = 5.3; and const VERSION_DATE = '2013-05-11';.

7. Lastly PSR-1 specifies that classes "should" either not have side effects or have side effects but not mix them in a class with one class to a file.

Side effects is doing other functionality not related to the declaring class, usually done by including files in the class.  Side effects means things like generating output, connecting to external services, modifying ini settings, emitting errors or exceptions, modifying global or static variables, reading from or writing to a file, and so on. This is difficult to do in some cases and is more a guideline, or something to strive for rather than a standard.

The PSR-1 standard is described on github.   If your interested in following the group, or becoming a member,  here is the FIG web site.   The group currently has a proposal to add to the PSR-0 standard some refinements, specifically on how to handle underscores in class names, and the group is currently looking at caching.

To cut to the essentials, and sum up,

class names should look like: class DarkSide{},

methods like: public function setDormLights(), and

constants like: const SERVER_NAME = ...

We'll cover the other PSR standards in future posts.

Posted in Naming Standards | Leave a comment

A PHP Singleton Flip-Flop, TRUE or FALSE

flip-flop2-225When I was learning computer internals, the hardware logic component that was the foundation of the computer was the flip-flop. The flip-flop was an electrical circuit that was either a one or zero. That usually translated to +9 volts or 0 Volts. In computer software, we call this a BOOLEAN, they're either set to TRUE or FALSE. After all, we do live in a digital, thus binary world. Let's have some fun with a couple of puzzles that deal with a BOOLEAN, true or false.

The other day, I was happily coding away, and ran into a little conundrum. I had created an event that fired globally after every save in my web application. The event allowed me to write additional code to alter some values depending on where in the application the user had saved his form, and then re-save the changed values back to the database. Everything went along swimmingly until I saved in my added code. Whereupon I looped around several hundred times, and hung my system, a good reason, to always do your coding on your local computer. Yep, you guessed it, my save in my additional code, triggered the global event that happened on every save, which triggered the save in my added code, and around and around we went until we stopped only where Apache knows.

Hmm, what to do to stop the loop? This is the pregnant pause that allows you to come up with a solution until I tell you mine.

Got it, well in pseudocode speak, here's how to stop the looping.

The event triggers on a user's save.
You set a "$flag" variable to TRUE initially to tell the additional code to run the first time.
You check to see if $flag is set to TRUE, if so run the added code.
Right before you save in your added code, you set the $flag variable to FALSE.
When you save your additional code, it fires the global save trigger.
You go back to your additional code, and this time the $flag variable is set to FALSE
You set $flag variable to TRUE, and return out of the added code without running it.

Simple! Not so fast. The $flag variable is a simple BOOLEAN, it's either TRUE of FALSE. How do we save our "$flag" variable on our system? The second pregnant pause for you to come up with a solution.

OK, let's go through our options.

1. We save the $flag variable locally as a private property of our class. Seems like it would work, but the problem here is initializing the variable, since every time you run an instance of the class you reinitialize the variable. Won't work, because if you go to FALSE, it will be reset to TRUE when re-initialized. Hmm...

2. We make a GLOBAL variable. This works, except every time I hear GLOBAL, I cringe. GLOBAL variables are vulnerable to any other coder who changes the variable to something else, or names a variable the same in their code, they are not exclusive. One of the reasons that "namespace" came into being. Since I work with a bunch of developers, who all work on the same application, and the application runs on a government, highly secure computer, I shy away from the GLOBAL variable. I do not have exclusive control of a GLOBAL. Let's find something else.

3. A $_SESSION variable. This works. My problem here is the flaky way new versions of browsers are handling variables created locally, and on a government web site, your not sure how long session variables are maintained, or how they are treated. It works, but less than ideal.

4. Use a Singleton. This works, and is the solution I choose, and will cover in the rest of this article. The singleton has the advantage in that it is accessible globally, but you need to call the class to get the private variable, and only one instance of the variable can exist, not multiple values that might occur with GLOBAL variables.

The reason for this article is to give you, my readers, a template for a TRUE or FALSE, flip-flop, singleton you can use in your own code anytime you need a BOOLEAN global variable. Here's the code:

/**
 * A singleton used as a secure BOOLEAN global variable
 * 
 * @param BOOL $flag  can only be TRUE or FALSE
 */
class saveFlagSingleton 
{
   private $flag; 
   private $defaultFlag = TRUE;
   private static $FlagObject = NULL;  // stores the instance of the object that stores $flag

// Only initiate the object within this class, "new" will not generate an instance outside this class
private function __construct() {}

// Prevent any copying or cloning of object
private function __clone() {}

// One instance only, generate the object to hold the variable
public static function getFlagObject()
{
   // Does the object already exist? If not make a new instance of the class
   if (empty(self::$FlagObject ))
   {
       self::$FlagObject = new saveFlagSingleton();
   }
   $FlagObj = self::$FlagObject;
   return $FlagObj;
} 

// Get current $flag setting
public function getFlag() 
{
   // if the Flag is empty, assign the default value
   if (empty($this->flag))
   {
      $this->flag = $this->defaultFlag; 
   }
   $theFlag = $this->flag;
   return $theFlag;
} 

// Set the current Flag
public function setFlag($setFlag)
{
   $this->flag = $setFlag;
}
} // End class

Only 47 lines of code with comments, and once you have this template, you can drop it in a file, and then call it when ever you need a global BOOLEAN.

Let go through the code, real quick. The variables are: $flag, a property of the object, which is where the current state of the TRUE or FALSE will reside. $flag is a private variable, so you have to use a method to access it, in the one, and only one, instance of the saveFlagSingleton class. The one instance of the class is called $FlagObject. There is a $defaultFlag variable used as a default value to initialize $flag.

OK, we have the singleton set up that we can drop into our code, how do you use it?
In your code, where you want to use a global TRUE or FALSE, first you have to include the class, like so:

require_once "saveflagsingleton.php";

We start through our code, and want to see if we will run our added code, or not, like so:

// This stops you from running the added code if $flag is set to FALSE
// Get the current flag state
$flag = saveFlagSingleton::getFlagObject()->getFlag();

if ( $flag === FALSE )
{
   $flag = TRUE;
   // Set the current Flag state back to TRUE for the next run
   saveFlagSingleton::getFlagObject()->setFlag($flag);
   // Return to bypass the added code
   return;
}

Now at the bottom of your added code, right before the added code save, we want to set the Flag back to FALSE so when the global event fires and starts through the added code again it will encounter a FALSE and won't run. Here goes:

// Stop global event from firing again 
$flag = FALSE ;
saveFlagSingleton::getFlagObject()->setFlag($flag);

// Now do the added code save

Well, as Bugs Bunny would say, "That's All Folks," or was that Elmer Fudd? Happy coding!

elmer

 

Posted in Design Patterns | Leave a comment

Vacationing with the new Nook HD

The new Nook HD with color menu


The new Nook HD
with color menu

It seems like every vacation I end up with a new eReader.  The eReader vendors are doing a good job at improving their products, marketing, and pricing their new features so you are willing to put out the bucks for the new version.  And they do make for very nice Christmas presents, not hard to pick out, and something everyone likes.  Thus, I received a new Nook HD for Christmas, started using it, and took it on my vacation to Jamaica.

The Nook HD has a high resolution 7" color screen.  I've noticed that eInk or color eInk has disappeared from the listed features.  It's like you shouldn't worry about the screen any more, but of course, I do.

This little tablet is really a computer, running the Android 4.03 operating system, allowing you to download and run your favorite apps.  It has 13Gb for storing your books or movies.  Books run from 100 to 300Mb, with 300Mb being about 800 pages.  That means, using an average of 250Mb per book, you can store about 52 books on the Nook before you have to archive back to Barnes and Nobles drive, plenty of space.  It has built-in WiFi and Bluetooth connectivity, and yes although only a 7" screen, you can surf the Internet, and send emails just like with a laptop.  I did mention that it has a high resolution of 243 pixels per inch with 16 million colors, which means NetFlix movies look good on the screen, the colors are gorgeous, and the audio comes with dual stereo speakers, volume control buttons, and headphone jacks, even a built in microphone if you want to dictate your next novel.  It's battery is rated at 10.5 hours reading and 9 hours playing videos.  Ok, we've established that the 7.7"x 5" Nook HD is a small 11.1 ounce computer with WiFi.

The new Nook is lighter and thinner than the old Nook and nice to hold in your hand.  We stayed at a hotel that advertised free WiFi.  I sometimes bring my laptop with me on vacation, but why did I need to take my laptop?  I had the Nook HD.  My answer was, I didn't, and I left it at home with out any problems from it not being there.  I wasn't going to work on vacation anyway, so I didn't need a keyboard, and for surfing the Internet, the on-screen keyboard works fine.  What else I didn't have to do was lug the normal five, or six trash novels I read in a week at the beach, they were all safely residing in my Nook.

readernook250


The old Nook

Since my prior vacations were with the original eInk Nook, and I've waxed on in a couple of articles about color eInk being the next new technology, boy was I wrong about that, it's worth doing a little comparison, since I have spent over a week, or so, using both Nooks over 10 hours a day.  On vacation, I tend to vegge out on the beach, under a canopy, and read all day, while I'm picking up those warm rays, dangling my feet in the warm sea, and watching the woman go by in their string bikinis, life is good.

I digress, OK, so the first thing that stood out, and I couldn't help but notice about the new Nook, was the touch screen.  Wow, it is extremely sensitive and responsive, at times I thought maybe a little too sensitive.  If you compare it to the original Nook, which had a little touch color window at the bottom, the touch sensitivity has improved 10 fold for the better, and the entire screen is touch sensitive, not just a little screen at the bottom.   And since the entire screen is touch sensitive, navigation is easier as you can hyperlink to each chapter and jump back and forth.

The page flipping buttons are gone from the old Nook.  To be honest, after flipping pages continually all day by pressing a button on the old Nook, I found my thumb getting a little sore.  On the new Nook it is done using the touch screen.  You can either swipe like your turning the page on a real book, or tap a side of the screen to turn the page.  This led to some problems when I would accidentally touch the screen and the page would flip.  I wasn't sure if I had tapped the left side to go back, or the right side to go forward.  Sometimes the pages flipped a couple of times which was confusing.  To find out where I was in the book, I had to flip back and forth to find the paragraph I was reading.  I have to admit this was annoying at times, and I found myself trying to be real careful on how I was holding the Nook while I was reading or changing body positions.

What I found disconcerting, at first, while I was reading was the screen kept changing directions.  The new Nook has automatic page orientation depending on how you hold the Nook.  You can hold the Nook horizontally, and have more words across the page, which is just like a normal book, and is pleasant way to read, or if you change the orientation of the Nook to vertical, the Nook will automatically switch the direction of the page.  You can actually spin the Nook a full 360 degrees and the eReader will orient the page on the fly as you turn the Nook.  That was neat at first, but as I flopped around changing my body orientation the Nook would sometimes flip the page when I didn't want it to.  This drove me nuts for a day or so until I realized by simply bringing up a menu with one touch, I could turn off the automatic orientation and freeze the page to one orientation, much better.

And now to what you all want to know.  How was the screen in sunlight?  The old Nook was superb in sunlight, eInk technology was made for sunlit screens, and the old Nook was a joy to read in the sun.  The letters just lit up.  The new Nook not so much so.  I found that in the sunlight I had to increase the brightness to maximum to be able to read.  It was easy to change the brightness, you touch the little menu icon at the top of the screen, the menu pops up, and you slide the brightness to max with a slider control.  But that maximum brightness you use in the sunlight was too bright for the hotel room and I had to turn it down.  I have to rate the old Nook better in the sun, of course.  But the old Nook didn't have a color screen, more a dull grey eInk screen, while the new Nook has a back-lit white screen.  The letters stand out more on the white screen, but are harder to see in the sun, because of that bright whiteness.  Now, to be honest, I was under a canopy, not in direct sun, and once I put the brightness to the maximum, I didn't have a problem reading.

Nook HD open    to a book


Nook HD open
to a book

Pushing up the brightness during the day led to another problem, the battery.  I could gradually watch the battery go down with max brightness.  I could still spend a good seven or eight hours without a problem, but I was more battery conscience than with the old Nook, and found myself plugging the Nook into the USB power adapter every time I went back to the room.  The new Nook has a wider power connector where it hooks to the Nook and I found myself wishing it had the same power jack as the old Nook and my cell phone.  This meant carrying two power cables on vacation.  I had previously purchased a two USB-to-wall socket adapter, so I able to charge each device at the same time.  Although the battery was a worry, I never really had a problem with running out of power.

To wrap this up, the old Nook seems like an old friend that I spent many hours enjoying, and I still know its there, just in case, but the new Nook gradually won me over.  Since I have both, and I still read on both, which one would I take on my next vacation, that's easy, the new Nook.  Yes, it has its quirks, which I talked about in this article, but they were quirks that I got use to.  What eventually won me over was the way the new Nook felt in my hand.  The quality of the print on the page.  The overall quality of the product.  The ease of use of the menu system with the touch screen across the entire screen, not just a small window.  The ease of browsing on the web.  In the end, I just liked the new Nook better.

Posted in eReaders | Leave a comment

Amazon Changes My Buying Habits, Again

amazon225Amazon became the gorilla in Internet retailing by operating at a loss for many years while it was getting started. They offered discount prices, gradually made an easy to use web site, added user reviews, worked hard at getting the orders correctly and timely to customers, and offered free shipping.

In my mind, it was the free shipping that got them to number one, and in the process forced a lot of businesses to close. I still lament the demise of Borders, which I attribute to people going to Borders, looking through the books to find the exact book they wanted, and then going on-line to buy it cheaper from Amazon with free shipping.

Amazon solidified consumer loyalty with user reviews.  People bought into the idea of letting everyone know what they thought about products.  Consumers gradually gave up on the need to  touch, see, and feel products in stores. Every one started to go to Amazon to find the best product by reading reviews.

Others tried to copy Amazon, but failed. Everyone still went to Amazon for reviews, and then to buy.   Amazon became the place to go for product reviews.  Who wanted to put their reviews on every site on the web.  And by continuing to offer discount prices, and free shipping, Amazon became hugely successful. They became the gorilla of eCommerce.

It's been a couple of years now, but I've noticed a gradual change in Amazon's philosophy.  It started with Amazon prime.  With Amazon prime, Amazon offered free two-day shipping for, I believe, initially $50 per year. It's now $79 a year. Why do this? That was my question when I was getting free shipping, and I was willing to wait a couple extra days.

Interestingly, during this period, I did notice, that either Amazon was opening more shipping centers, or shippers were getting more efficient, because some times items I purchased would start arriving early. Instead of the projected two weeks, it would get to me in one week. No need for Amazon Prime, I was a happy camper.

Not anymore, I'm here to report that Amazon has changed. The bean counters have arrived, and profit is king. Let's start squeezing consumers every where we can.

I don't know if any one else has noticed, but free shipping is pretty much history. It's gone. To be fair to Amazon, it definitely costs more to ship, because of increasing gas prices, but I have noticed that Amazon shipping charges seem high.

I went to purchase a headset from Amazon. I did my careful review, picked out the headset I wanted. The headset was $15.98, Amazon shipping was $8.48. I wanted a picture frame, it cost $12.99, shipping was $8.25, and finally a pair of warm socks cost $19.55, shipping was $8.09. Socks you can put in a small box and ship for $5.00 at the Post Office.  What was worse, if I combined all three items into one order the shipping was the total of all three items individual shipping.   I understand it, but it didn't seem right to me.

That prompted me to compare prices, and what I found was, that in-addition to many online eCommerce sites, brick and mortar stores were cheaper for the same item. I found many stores, like Target and Walmart, and even Macy's lower in price.   From my perspective, that meant that Amazon was raising its prices, and was no longer the place to go for discount prices. They must feel they have consumers locked in, and are now going to turn that into increased profits.  Many stores have started out at discount prices, gained a market share, and then gradually tried to raise their prices, only to lose their market segment, and gradually fail.

Amazon, going forward, may start getting some of the medicine it initially dished out to others, like Borders.  I'm not saying that Amazon is going to close up shop any time soon, but brick and mortar stores can now compete.

They can order in bulk directly, and therefore, their shipping charges will be lower, which means they can offer consumers a lower price and immediate access to products without shipping.

This can only be good for every one, but Amazon. Oh, I'll still go to Amazon for reviews, but now I'll add a couple of extra steps, I'll do a price comparison, and I'll find out if stores near me have the product in stock at a better price. Yes, its a little more effort, but not that much, and I get the product immediately.

In short, in my mind, Amazon has lost its luster. It's now just another eCommerce site.  Admittedly, still my first place to go to research products, but once I make my choice, Amazon is no longer an automatic buy like it use to be.

What stops me from clicking that "Place your order" button, and triggers my search for a better buy is the shipping charge.   No free shipping means I can get a better price somewhere else.   Isn't it ironic,  Amazon trained me to buy on-line by offering free shipping, now they are training me to go elsewhere by taking it away.

Posted in Editorials | Leave a comment