Tuesday, December 31, 2013

5 Rules for Outsourcing Interviews

Before I get to the actual rules, let me tell you a story. A few weeks ago, I was approached by an HR Associate of a Bangalore-based e-Learning Solutions company. They had an "Engineering Manager" opening, for which this HR fellow thought my profile was well suited. After going through the Job Description, I felt the role was a bit more "technical" than I would like. But then again, most companies do give a technical slant to their Project Manager JDs, to ensure that the candidate has some past coding experience, instead of being a typical "MBA-pass manager". So I asked him to go ahead and schedule a telephonic discussion. Soon he called me and told me that his CTO Mr. Charles Dickhead (not his real name) would call me on the morning of 27th December. He also said that he'd send a confirmation email, which never came. Still I remained available at that time, just in case CD gave me a call. When the call didn't come, I went on with my day, and forgot about the position.

Out of the blue, the HR guy called me again yesterday and apologized for the non-availability of CD due to Christmas (on 27th December???) and confirmed the rescheduled telephonic interview for today afternoon. Since I've been giving many interviews of late for Project Manager positions, I did not feel it necessary to do any specific preparation. If you've managed projects for 7 years, including Development, Production Support and Upgrade projects, across various technologies, you can manage practically any IT project. All that an interview needs to check is the depth of your PM experience, along with your personality and fitment to the organization. But CD apparently had other ideas, because he outsourced the job of taking my interview to someone else, let's call him Mr. AK-47. To my horror, this guy followed up the standard, much-abused "tell me more about yourself" question with a set of queries that are normally reserved for freshers straight out of engineering college.

"What are the differences between the deployment of a Java project and that of a PHP project?" was followed by "What are the key features of MVC architecture?" By the time I'd wriggled my way out of those two, I realized that AK was at best a Technical Architect, at worst a Tech Lead, and most likely that amorphous entity called a Project Lead. He had probably never met a person with 14+ years of IT experience, much less interviewed one. As I desperately tried to talk myself out of jumping through the window, AK came up with a classic: "What are the 4 pillars of Object Oriented Programming?" As I hemmed and hawed, not knowing whether to kill him or strangle myself, I managed to blurt out "polymorphism" and "inheritance". Sensing that I was choking on the question, AK helpfully came up with "abstraction" and "encapsulation". At this point I was wondering how to end this nightmare, when AK went and outdid himself, if at all that was possible. He said, "Give a one-line definition of each of the 4 pillars." That was it for me; I openly told AK that his questions were far too technical for me, and that I couldn't answer them. AK decided to put me out of my agony by ending the interview and offering to convey "his feedback" to the CTO.

So, without further ado, here are the 5 rules you need to follow while outsourcing interviews, which you were supposed to take, to your juniors:

1. Team Member interviews can be outsourced to Team Leads and above
2. Team Lead interviews can be outsourced to Project Leads and above
3. Project Lead interviews can be outsourced to Project Managers and above
4. Project Manager interviews can be outsourced to Senior Managers and above
5. Never break any of the above 4 rules. Never! NEVER EVER!!!

Friday, December 27, 2013

Leadership and Transparency

This morning, while reading the Economic Times, I came across this quote from the global HR head of one of India's leading Consumer Products & Services companies: "In turbulent times there is a need for greater transparency at the workplace, which will lead to higher accountability, responsibility and responsiveness on [the employee's] part". This struck me as a very powerful idea, one that I believe needs to be implemented urgently by all companies.

Whether your company has just lost a big deal, or has run out of working capital in a recession year, or is facing a hostile takeover by a rival organization, be transparent - go ahead and tell your employees all about it. Also tell them the short-term and long-term impacts of the problem. Normally, whenever a company faces tough times, the natural reaction of the leadership is to shut themselves off from the employees. They feel that, by not conveying the bad news for as long as possible, they can protect the employees from demotivation and low productivity. But we need to realize that such an information blackout normally has the opposite effect on our team. An employee who knows what is going on is more secure mentally, since there is no uncertainty about the situation of the company. Such an employee has two straightforward choices - either stick with the company and help it tide over the bad times, or leave immediately for greener pastures. On the other hand, an employee who is kept insulated from the bad news will soon realize that something is being hidden from him but at the same time will not be sure as to what that hidden matter is. This uncertainty will keep preying on his mind continuously, thereby reducing both his immediate productivity and his long-term engagement with the organization.

Another aspect of transparency is to treat all employees equally during a crisis. If you apply one set of rules for some employees, and another set of rules for others, you run the risk of alienating both groups by making each think you favored the other. For instance, if you implement a cost cutting drive, ensure that applies to everyone, including the leadership team. If the leaders don't lead by example, they will find it difficult to push through any unpopular measures in their respective departments. Or else, if there is a cash crisis and salary payments are delayed, ensure that all the employees are paid at the same time or nobody is. If you decide to pay the junior employees first, saying that they are more dependent on salary income, the seniors will definitely support you. But somewhere in their minds, they will feel betrayed and the first thought of quitting will begin to arise. A third instance where transparency is needed is during appraisals. When one employee gets a good rating, or an award, or a promotion, it is your responsibility as a leader to explain to the rest of the team why that person is getting the special recognition. This will guard against bad blood and allegations of favoritism.

Wednesday, December 11, 2013

RoR Music Database Project

Finally, I've created a Rails + SQLite version of my favorite practice project - the Music Database. This one looks very different from my other (Perl, Python, PHP, ASP, ASPX) implementations of the project - as Ruby is an object-oriented language, I tried to model the application as closely as possible to real life. Usually I store the details of each song in a row of the database table, with the album details (Album Name, Year, Artist Name) being repeated for multiple songs. But here I made Album the primary model and Song a secondary one. So the user has to first create an album and then add multiple songs to it. Here are the steps I followed, once I had the design ready in my mind:

  rails new MusicDatabase
  cd MusicDatabase
  rails generate scaffold Album albumname:string albumartist:string albumyear:datetime
  rake db:migrate

Edit the file "config\routes.rb" to open "views\albums\index" by default, by adding the line:
  root :to => "albums#index"

rails generate model Song songname:string album:references
rake db:migrate
rails generate controller Songs index show new edit

Edit the file "controllers\song_controller.rb" to have the standard methods for showing, adding, editing and deleting songs

Edit the files under the "views\songs\" directory to have the standard forms for showing, adding, editing and deleting songs

In my case, because of the form code that I copied from the Rails tutorial, I also had to edit my Gemfile to include the line "gem 'dynamic_form'" and then do a "bundle install". And thus, I completed my Ruby on Rails "self test" by getting the Music Database project running successfully

Wednesday, December 4, 2013

Steps Taken to Revive Galaxy Tab 2 P3100

When my tab recently suffered a battery drainout issue, these are the steps I took to revive it:

Charge battery to 99%
Perform factory reset
Connect to Wi-Fi
Provide Samsung account settings
Provide Google account settings
Update Samsung apps
Power off
Insert SIM card and Micro SD card
Power on
Save GPRS settings
Install essential apps only (Clean Master, Facebook, Blogger, MyMail in my case)
Update stock Android and Samsung apps as needed
Add apps and widgets to home screen as needed

Friday, November 22, 2013

SOLVED: Rails with MySQL on Windows

For the last couple of days, I was struggling to get Rails to talk to MySQL on Windows. Though I was able to install the "mysql" gem, I got an error message when I tried to run the "rake db:create" command for creating the database tables needed for my model. Web searches revealed many detailed discussions on the problem, but no definite solution. Whatever approach I tried only resulted in a different error message. Finally, against the run of play (as cricket commentators would say), I was able to get things working. So here are the steps I followed, for the benefit of others who may be facing the same issue:

1. Install Ruby and Rails using the RailsInstaller - I used version 1.3, which provides Ruby 1.8.7 and Rails 3.0.7, along with other related packages like Bundler and DevKit

2. Install MySQL Community Server - I already had version 5.5.23

3. Install the mysql gem:

gem install mysql

4. Carefully read the message from the mysql gem installer - I got:

You've installed the binary version of mysql2. It was built using MySQL Connector/C version 6.0.2. It's recommended to use the exact same version to avoid potential issues.

At the time of building this gem, the necessary DLL files where available in the following download:

http://dev.mysql.com/get/Downloads/Connector-C/mysql-connector-c-noinstall-6.0.2-win32.zip/from/pick

And put lib\libmysql.dll file in your Ruby bin directory, for example C:\Ruby\bin

5. Download the exact same version of the MySQL C connector as mentioned in the message you see. Get the zip archive, not the MSI installer. Simply extract the "lib\libmysql.dll" file and put it in your "Ruby\bin" directory (you don't really need the rest of the C connector files).

6. Add a new line "gem mysql" to the Gem file of your Rails project.

7. Replace the (sqlite) contents of your config\database.yml file with:

development:
  adapter: mysql
  encoding: utf8
  database: blog_development
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

Now, when you run the "rake db:create" command, it should work without any issues. Even before that, you can test the MySQL connectivity using irb (the Interactive Ruby shell):

C:\Documents and Settings\User>irb
irb(main):001:0> require "Rubygems"
=> true
irb(main):002:0> require "mysql"
=> true
irb(main):003:0> Mysql.connect("localhost", "root", "", "phpwork")
=> #<Mysql:0x2cdfca8>
irb(main):004:0>

Tuesday, November 19, 2013

Hi, Ruby!

In the last couple of months, I've more or less completed my target of revising the basic concepts of Perl, Python and PHP. So I decided to check out a relatively newer member of the Open Source Programming Languages family. Ruby, along with the Rails framework that is based on it, has captured the imagination of web developers worldwide.

Ruby is said to be a truly object-oriented language that is easy to learn, and has rich libraries that are easy to extend. The Rails framework includes everything that you would need to create a database-driven web application using the MVC pattern. As it needs minimal configuration, you can develop applications faster than with other frameworks.

At least that's what the tutorials say. Today I'll put these statements to the test by (a) learning the basics of Ruby, (b) installing Ruby, (c) running a Hello World program, (d) running a simple Embedded Ruby program, (e) installing and testing the Rails framework, and (f) creating a Rails + MySQL version of my good ol' music database project.

Note that I'll follow the "Ruby on Rails Introduction" tutorial on tutorialspoint.com, which was the first Ruby tutorial I found, and use their sample code. After going through the first few pages of this tutorial, I installed Ruby from http://rubyinstaller.org/

I then tested the Hello World program and the simple Embedded Ruby program from the tutorial. Next, I tried to install the Rails framework using the "gem" utility that comes with Ruby. This utility can be used to install Ruby packages, called "Gems".

But I ran into an error during the Rails installation, due to the absence of the necessary build tools for the 'atomic' native gem. To get around this issue, I had to first install the Ruby Developer Kit. I downloaded the installer from the same URL as Ruby - http://rubyinstaller.org/ - and then followed the step by step installation instructions given by http://learnwebtutorials.com/.

(Note: An easier way is to visit the RailsInstaller website and install Ruby, Rails and many other packages at one go)

Next I had to create a demo Rails project as given in the tutorial, run the WEBrick web server that is bundled with Rails, and test the demo page from my browser. Note that the right command to create a demo Rails project is "rails new demo" and not "rails demo" as given in the tutorial. Also, the right commands to start the WEBrick web server are "cd demo" followed by "rails server". In both these cases, the commands given in the tutorialspoint.com web tutorial seem to be outdated ones.

Thus I've completed 5 of my 6 objectives for today, viz.: (a) learnt the basics of Ruby, (b) installed Ruby, (c) ran a Ruby Hello World program, (d) ran a simple Embedded Ruby program, and (e) installed and tested the Rails framework. Creating a Rails + MySQL version of my music database project will take more study and, quite possibly, a lot of trial and error. So I'll try and complete that objective later this week. Meanwhile let me search for some more good Ruby tutorials on the Web.

Monday, November 11, 2013

Skills for Starting a Company

A young trekker friend recently asked me what are the key skills he would need for starting his own company, which is something he intends to do in the future. Since we were just chatting, I asked him for some time to put together my thoughts on this subject. Not that I'm an expert on the topic but I can surely speak from second-hand experience, having been part of many startups and small IT companies. Some of these have done reasonably well, others have done spectacularly badly and some have just maintained a status quo (which I personally believe is worse than a spectacular failure, but that's another blog post). So here are the 5 top skills that I believe my friend needs to develop before he starts his own company:

Communication
Any company needs to sell something - an idea, a product or a service - in order to succeed. So the very first skill you need is the ability to communicate your company's offerings. Of course, you can always employ a sales guy to handle the actual selling but as an entrepreneur, you need to be in the forefront of marketing your company and its products. Years before you actually start your firm, you need to start building a network of contacts. This network will eventually give you the leads that your sales team would exploit, to win business for your company. Once you get the deals, you need to keep communicating with your customers to ensure timely payments, to get contract renewals or new deals and to gather more leads.

Leadership
In most fields, you cannot be a one-man company. That may be how you start off but eventually you have to build and lead a team of specialists in various functions like sales, delivery, support, admin, etc. Leading is not just about coordinating - you have to define your company values, communicate those to the team, and lead by example. Communication plays a very key role in keeping your team engaged. Initially there may be hiccups and setbacks. But if you keep your team informed about the problems, they will support you through thick and thin. Even when the business is doing well, you cannot afford to neglect your communication duties as a leader. Many promising companies have floundered by losing the support of their core team.

Problem Solving
Many people wonder whether technical skills are necessary to start your own company. For example, do you need to be a baker to start a cake shop? Or do you need to be a web programmer to start a dot-com? The answer is clearly No. But at the same time, you cannot be totally unaware of the subject. Even if you have experts to do the dirty work, you still need to understand the problems your business is facing and you need the skills to solve those problems. Simply put, problem solving is the process of identifying, analyzing and solving problems. This is a skill that you pick up through work experience more than anything else. So I would advise my friend to work in the chosen field for 5-10 years before he starts his own company.

Empathy
Earlier, I talked about the importance of communicating with your team about your successes and failures. But mere communication is not enough, especially in tough times. Telling your employees about your problems will not automatically buy you their support. For example, if the company runs into losses in a recession year, you cannot just expect the team members to work for a fraction of their salary. You need to be able to put yourself in their shoes and understand their problems, especially financial ones. Then you need to provide solutions for those problems, even at the cost of your profit calculations. At the same time, you need to ensure that you are investing in the right people, those who would stick with you in the long run. 

Humility
In my view, it is easier to be a leader in a period of failure than in a period of success. The intoxicating sweetness of success has a tendency to go to your head, impairing your judgement and taking you to the edge of pitfalls. Maybe CXOs of large corporations can afford their eccentric ego trips and subsequent losses, but you cannot. Keep yourself humble at all times and resist the temptation to believe the larger than life image of your company that is created by your marketing team. Remember that the competition is always out there, waiting for you to make one false move. Stay focussed on your customers, stay in touch with your employees and stay rooted to your company's values and core competencies and your business plan. 

Friday, November 1, 2013

Excel output from Perl script

In an earlier post, I had explained how to output some tabular data from a PHP script into an Excel sheet using PHPExcel. Today, I shall explain the Perl equivalent, using a module named Spreadsheet::WriteExcel. This module can be easily installed using PPM. By looking at the documentation and the code examples, we can quickly rustle up our own Perl code to create an Excel sheet containing the songs data from our famous music database.

    # Create a new Excel workbook
    my $workbook = Spreadsheet::WriteExcel->new('music_list.xls');
    
    # Add a worksheet
    my $worksheet = $workbook->add_worksheet();
    
    #  Add and define a format for title row
    my $format = $workbook->add_format(); # Add a format
    $format->set_bold();
    $format->set_color('black');
    my $slate_grey = $workbook->set_custom_color(40, '#6D7B8D'); # slate grey color
    $format->set_bg_color($slate_grey);
    $format->set_align('center');
    
    # Write the Excel title row using the new format
    $worksheet->write(0, 0, "Song Title", $format);
    $worksheet->write(0, 1, "Artist Name", $format);
    $worksheet->write(0, 2, "Album Title", $format);
    $worksheet->write(0, 3, "Year Title", $format);
    
    # Increase the column width for clarity
    $worksheet->set_column('A:D', 25);

    # Define the format for the cell borders
    my $cell_border_format = $workbook->add_format(border => 1);

    if ($row_count == 0) {
        $worksheet->write(1, 0, "No records");
    } else {
        for (my $i=0; $i < $row_count; $i++) {
            # Write the actual table contents and also set the cell borders
            $worksheet->write($i+1, 0, $excel_content->{"a" . $i}, $cell_border_format);
            $worksheet->write($i+1, 1, $excel_content->{"b" . $i}, $cell_border_format);
            $worksheet->write($i+1, 2, $excel_content->{"c" . $i}, $cell_border_format);
            $worksheet->write($i+1, 3, $excel_content->{"d" . $i}, $cell_border_format);
        }
    }

One catch is that the Spreadsheet::WriteExcel module cannot overwrite an existing Excel file (by design, to avoid accidental data loss). So let us put in a bit of code to delete the existing file, if any.

    # Check if Excel file already exists
    if (-e 'music_list.xls') {
        # Try and delete old Excel file
        if (unlink('music_list.xls') == 0) {
            # Show error message if delete fails
            print "Old Excel file could not be deleted";

            # Show the HTML footers and exit
            &tail($dbh);
            exit(0);
        }
    }

Wednesday, October 23, 2013

Small Retailers as a Market for Tech Startups

Last week, ET published an article on how small and medium retailers wanting to take their business online are turning to technology startups for help. These typically charge Rs 1,000 to Rs 4,000 a month for technology services ranging from building websites to linking them with payment gateways and logistics providers. When compared to the potential earnings from doing big projects for large customers, these amounts are negligible. Still some of these companies are confident of being profitable soon. This got me thinking on how it makes business sense for these startups to target retailers as a market for cloud-based services. To be profitable with this model they would need huge volumes, meaning a large number of retailers. But are Indian retailers ready to take the Web plunge?

Let's look at it from a retailer's point of view. Here shall assume that the retailer in question is not just a grocer or a hardware store owner. He/she has one or more specialized products or services and seeks to target a particular segment of customers. Consider an exercise equipment shop, for example. For such an entrepreneur, normal Above The Line advertising alone will not bring in customers. Nor will word of mouth publicity get them the large number of leads they require, given their low conversion ratio of leads to sales. Since theirs is a lifestyle product, they would need to reach out to their target audience through micro level focused messaging. An online presence, including social media outreach, would be an essential part of their strategy. Here's where a tech startup can help.

Social media advertising and reviews on popular forums can attract the customer's attention to either the physical shop (where it is arguably easier to close a sale) or at least a website. If the website is designed and built well, and has payment gateway integration, it is possible to push the customer into buying the product online itself, while a tie-up with a logistics provider ensures that the product is delivered to the customer's house within an acceptable timeline. If the customer can be coaxed into writing a Web review of the product, that in turn would bring in more leads for the entrepreneur. On seeing that all these services are available for a moderate monthly payment, other retailers would jump on the bandwagon. So it's a  win-win situation for the entrepreneurs as well as the tech startup.

Tuesday, October 22, 2013

Object-Oriented Programming in Perl

My first and last brush with Perl OO programming was back in 2008. I was in the Netherlands with a couple of colleagues, getting "KT" for a set of small e-commerce applications whose support was being outsourced to India. We were horrified to see that the code was object-oriented, with many layers of inheritance, which made it extremely difficult to learn. As part of the Knowledge Transfer, we were asked to create installers and use them to get the applications running on a new server. But we would inevitably run into errors, which would send us hunting from file to file and class to class to try and find the ultimate parent class. Even the Dutch team that had been supporting the code for a few years did not know the nitty-gritty of the inheritance - they  had only learnt enough to support the applications on a day to day basis.

Having learnt C++ and Java earlier, I had realized then that Perl is not the best language for object-oriented programming. But the fact that it supports OO means that you need to know the basics, just in case you face a situation like I did. There are many online tutorials available on the subject but the best ones come straight from the horse's mouth, viz: the perlootut tutorial and  the perlobj language reference. After going through these, you may feel confident enough to create your own class and then test it with a simple script. I first created a very basic class called Muzak to represent the songs from my music collection. Each Muzak object has up to 4 attributes - a song name (mandatory), artist name, album title and year. It has 1 method - artist() - that returns the artist name. I put the class in a Perl module called Muzak.

Muzak.pm

package Muzak;

# Constructor
sub new {
    my $class = shift;
    my ( $song, $artist, $album, $year ) = @_;
    
    if ($song eq "") {
        die "Muzak object requires at least Song Name attribute";
    }

    my $self = bless {
        song => $song,
        artist => $artist,
        album => $album,
        year => $year,
    }, $class;

    return $self;
}

# Method: Get artist
sub artist {
    my $self = shift;
    return $self->{artist};
}

1;

Note that the "1;" at the end of the .pm file is critical. If you miss it, the Perl interpreter will throw an error while testing the script, which would look like "Muzak.pm did not return a true value at test_muzak.pl line 6". Also note that the check for non-blank song name is also not mandatory to create a working class - it is just a logical check that I added.

test_muzak.pl

use Muzak;
use feature qw(say);

# Create new Muzak object with all 4 paramaters
my $muzak1 = Muzak->new('Aqualung', 'Jethro Tull', 'Aqualung', '1971');

# Print the song artist name
say "Artist1 is " . $muzak1->artist();

# Create new Muzak object with only 1 parameter
my $muzak2 = Muzak->new('Bouree');

# Try printing the song artist name
say "Artist2 is " . $muzak2->artist();

# Try creating new Muzak object with 0 parameters
my $muzak3 = Muzak->new();

# Try printing the song artist name
say "Artist3 is " . $muzak3->artist();

There's a lot more to explore in Perl OO programming. I can write code that is much more complicated, like those Dutch applications (which were created, if I remember correctly, by a UK firm). More importantly, I can write code that is more useful than just playing around with song details. But that's another day, another class, another blog post

Friday, October 18, 2013

Excel output from PHP script

Let's say you've written a PHP script that queries a data source (say a MySQL database) and displays the output in the browser. Now you want to export this data to an Excel sheet that the user can print or process further. What are the different ways of doing this?

The first way I ever learned was to simply set the PHP content type header, like "Content-type: application/vnd.ms-excel; name='excel'". This prompts the user to open or save an Excel sheet, which would contain our tabular content. But in this method, you would not have any control over the formatting of the Excel sheet, such as borders, fonts, colors, etc.

If you want to generate a well-formatted Excel sheet, you can use the PHP library called PHPExcel, which can be downloaded from here. Just copy part of the zip file contents (see the "install.txt" file) to a sub-directory on your web server document root and you can get going. It is easy to save your tabular content to an Excel file on the server, using PHPExcel.

The code required for creating the Excel file is fairly simple, and you can put it together by looking at the examples given in the PHPExcel zip file. If you get stuck, say on a formatting issue, you can always google the solution. PHPExcel seems to be quite popular and so, more likely than not, your question would have been answered on one of the coding forums.

Here is my code for saving my Music Database List content as an Excel file:

/* Include PHPExcel */
require_once '../../Classes/PHPExcel.php';

// Create new PHPExcel object
$objPHPExcel = new PHPExcel();

// Set document properties
$objPHPExcel->getProperties()->setCreator("Ajay Ramakrishnan")
    ->setLastModifiedBy("Ajay Ramakrishnan")
    ->setTitle("Music Database List")
    ->setSubject("Music Database List")
    ->setDescription("Music Database List, generated using PHPExcel.")
    ->setKeywords("Music Database PHPExcel")
    ->setCategory("Music Database List");

// Add title row to Excel file
$objPHPExcel->setActiveSheetIndex(0)
    ->setCellValue('A1', $a[0])
    ->setCellValue('B1', $b[0])
    ->setCellValue('C1', $c[0])
    ->setCellValue('D1', $d[0]);

// Set the title row font to bold and background color to light slate grey
$header_range = "A1:D1";
$objPHPExcel->getActiveSheet()->getStyle($header_range)->getFont()->setBold(true);
$bgColorArray = array(
                    'fill' => array(
                        'type' => PHPExcel_Style_Fill::FILL_SOLID,
                        'color' => array('rgb' => '6D7B8D')
                    )
                );
$objPHPExcel->getActiveSheet()->getStyle($header_range)->applyFromArray($bgColorArray);

// Loop through the existing data rows
for ($i=2; $i <= $row_count; $i++) {
    $objPHPExcel->setActiveSheetIndex(0)
        ->setCellValue('A' . $i, $a[$i-1])
        ->setCellValue('B' . $i, $b[$i-1])
        ->setCellValue('C' . $i, $c[$i-1])
        ->setCellValue('D' . $i, $d[$i-1]);
    }

// Resize the columns
$objPHPExcel->getActiveSheet()->getColumnDimension('A')->setAutoSize(true);
$objPHPExcel->getActiveSheet()->getColumnDimension('B')->setAutoSize(true);
$objPHPExcel->getActiveSheet()->getColumnDimension('C')->setAutoSize(true);
$objPHPExcel->getActiveSheet()->getColumnDimension('D')->setAutoSize(true);

// Set the border for all the non-empty cells
$i = $i - 1;
$styleArray = array(
        'borders' => array(
            'left' => array(
                'style' => PHPExcel_Style_Border::BORDER_THIN,
            ),
            'right' => array(
                'style' => PHPExcel_Style_Border::BORDER_THIN,
            ),
            'top' => array(
                'style' => PHPExcel_Style_Border::BORDER_THIN,
            ),
            'bottom' => array(
                'style' => PHPExcel_Style_Border::BORDER_THIN,
            ),
        ),
    );
$objPHPExcel->getActiveSheet()->getStyle('A1:D' . $i)->applyFromArray($styleArray, False);

// Rename worksheet
$objPHPExcel->getActiveSheet()->setTitle('Music_DB_List');

// Set active sheet index to the first sheet, so Excel opens this as the first sheet
$objPHPExcel->setActiveSheetIndex(0);

// Save Excel 2007 file
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save(str_replace('.php', '.xlsx', __FILE__));

Friday, October 4, 2013

Parsing HTML pages using Mojo::DOM

After my previous post, I successfully wrote a Perl script to parse an XML file that I had retrieved (from an RSS feed) using Perl and cURL. XML parsing and manipulation is simple enough, if you use the XML::Simple module. But what if the web page you are retrieving with Perl and cURL is an HTML page? And what if you have to make some changes to the HTML code before you render it in your browser? This would require a module that allows you to access individual DOM elements and even modify them. That is how I learned about the Mojo::DOM module, which is part of a package called Mojolicious that you can get on CPAN. Mojolicious calls itself "a next generation web framework for the Perl programming language". You can learn more on their website. Installing it on your machine is simple enough, using the command:

ppm install Mojolicious

Meanwhile, I decided to retrieve a particular web site's home page, make a couple of changes in the code, and render the same page in my browser. The changes were: 1) I would remove their Google analytics code, which was enclosed in a <script> tag pair, and (2) I would ensure that all references to stylesheets and images are prefixed with the URL of that particular web site, so that the web page in my browser appears identical to the original. Here are some of the interesting things that I learned about Mojo::DOM while completing this script, explained usingcode snippets:

$dom = Mojo::DOM->new->xml(0)->parse($response_body);

* Here I have created a new Mojo::DOM object, by parsing the response from my cURL call. The xml(0) is to tell Mojo::DOM to use HTML mode instead of XML mode

my @links = $domref->find('[href]')->each;

* Here I am telling Mojo::DOM to return all HTML tags having a 'href' attribute. I can then go through the @links array using foreach()

$_->attr(href => $linkhref);

* Here I am replacing the value of the 'href' attribute of a particular tag to a string $linkhref, which is actually a modified version of the original value

$_->replace_content($styletext);

* Here I am replacing the entire contents of a particular <style> tag pair with a modified version of the original contents. Interestingly the replace_content function has a bug - it replaces all instances of double quotes with the HTML entity code equivalent '&quot;', which may cause problems in the HTML output. So you need to change the HTML entity code back to double quotes before the end of the script

say "$domref";

* Here I am outputting the modified HTML code to the browser. For those who are not aware, say is the Perl equivalent of Java's println. It saves you the trouble of appending a "\n" at the end of every print statement. Using say requires the line "use feature qw(say);" along with your module declarations

Wednesday, September 25, 2013

Perl & Curl have my Head in a Whirl

I had recently written a PHP script to read a URL using cURL. Today, I thought I'd convert it into a Perl script. PHP has built in support for cURL, using functions like curl_init(), curl_exec() and curl_close(). In Perl, you have to install and use a CPAN module called WWW::Curl. At first glance, it seemed a simple task. But the problem is that on Windows, you can't simply download the module using the usual command "cpan WWW::Curl". You have to download the source file package and manually install the module. For this, you also need the source package of the cURL libraries. You can't just download and use the "curl" binary, the way you would if you just wanted to run the "curl" command from the DOS prompt. Anyway, here are the steps to follow...

* Ensure a C compiler is installed and available on the PATH. If not, get GCC by installing the Perl MinGW package:

ppm install MinGW

* Download the latest cURL libraries for mingw from the cURL website:

http://curl.haxx.se/download.html

* Unzip the folder somewhere (say C:\curl-7.32.0)

* Download the CPAN module WWW::CURL from CPAN:

http://search.cpan.org/~szbalint/WWW-Curl-4.15/

* Unizp the folder somewhere (say on your Desktop). Edit the Makefile.PL, making the following changes:

1. Comment the lines following the comment "This is a hack."

2. Change the "my @includes..." line to:

my @includes = qw(C://curl-7.32.0//include);

3. Change the "my ($cflags..." line to:

my ($cflags,$lflags, $ldflags) = ('-I"C://curl-7.32.0//include"','-L"C://curl-7.32.0//lib"','-lcurldll -lcurl');

 4. Change the "open(H_IN, "-|", "cpp"" line to:

my $cmd = "cpp $curl_h";
open(H_IN, $cmd) and $has_cpp++;

5. Change the "'LIBS'         => "$ldflags $lflags..." line to:

'LIBS'         => "$lflags $ldflags",        # e.g., '-lm'

* Note that this last change is very important, or else you'll spend 2 hours debugging a linker error - as I unfortunately did

* Run the command:

perl Makefile.PL

* Run the command:

dmake

* Run the command:

dmake install

* Try running your test Perl script. If you get an error, usually as a popup, that says "The procedure entry point ERR_remove_thread_state...", just add "C:\curl-7.32.0\bin" at the beginning of your PATH. This error occurs when your system picks up a wrong version of "libeay32.dll", probably from your installation of SSL VPN or some other application

* Another issue you could face is that your Perl script works fine from the command line but when you run it in Apache, you get an internal server error while loading the WWW::Curl Perl Module, which you can confirm by checking the Apache error log. This is because the "C:\curl-7.32.0\lib" folder is not in your PATH, and needs to be added

Now you're ready to go - write that Perl program to read a URL using cURL. Thanks to Niranjan Prithivraj, whose post was partially helpful during my installation. Hope this post would be useful to someone else, just like Niranjan's post helped me

Saturday, September 14, 2013

Defeat Browser Hijackers!

Ever faced a situation where you were careless while installing some software (mostly a free utility) and your browser got hijacked by ask.com? It not only changes your home page and default search provider, it also prevents you from changing the home page back to what you want. So, even if you change the home page from the "Settings" menu, you'll find that "search.ask.com" opens up the next time your start the browser. After an hour of effort, I finally found a permanent fix... Go to "Add/Remove Programs" and uninstall the application called "Movies Toolbar for Chrome (Dist. by Bandoo Media, Inc.)". Then go to your Chrome settings and change the home page once again, this time for good

Thursday, September 12, 2013

A Small XSLTip

While making some minor changes to my website recently, I encountered an interesting problem - that of displaying a URL on an XML-XSLT web page. But before I get into the problem and the solution, time for some introductions for the benefit of newbies...

XML: Extensible Markup Language (XML) is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable. It is a textual data format with strong Unicode support (more on Wikipedia)

XSLT: Extensible Stylesheet Language Transformations (XSLT ) is a language for transforming XML documents into other XML documents, or other objects such as HTML, plain text or XSL Formatting Objects for processing into other formats (more on Wikipedia)

My XML code was as follows:

 <lines>
  <line name="Company" linetext="Capgemini Consulting India Pvt. Ltd." />
  <line name="Description" linetext="Capgemini is a global leader in consulting, technology, outsourcing and local professional services. It employs more than 83,000 employees globally." />
  <line name="My tenure" linetext="2004-2012" />
  <line name="My role" linetext="Manager" />
  <line name="Comments" linetext="Cap was my first big break and the career growth I got was phenomenal. Indeed, the Capgemini stint totally changed me at a personal level." />
  <line name="Website" linetext="http://in.capgemini.com" />
 </lines>

The challenge was to ensure that the website name appeared as a valid URL, whereas the other lines appeared as plain text. This meant that the highlighted "line" with the "name" of "Website" had to be processed in a different way from all the other "lines". After some web searching, I came up with the following XSLT code for processing the "line" tags:

 <xsl:template match="line">
  <tr>
   <td width="30%" align="right" valign="middle" class="itemtext">
    <b><xsl:value-of select="@name" />:</b>
   </td>
   <td width="70%" align="left" valign="middle" class="itemtext">
    <xsl:if test="@name='Website'">
     <a href="{@linetext}"> 
      <xsl:value-of select="@linetext"/>
     </a>
    </xsl:if>
    <xsl:if test="@name!='Website'">
     <xsl:value-of select="@linetext" />
    </xsl:if>
   </td>
  </tr>
  <tr>
   <td colspan="2" align="center" valign="middle">&#160;</td>
  </tr>
 </xsl:template>

Hopefully the above XSLT code is self-explanatory. If not, feel free to contact me for a discussion

Wednesday, August 14, 2013

Tips on Converting PHP to Perl-CGI

The story today is very similar to yesterday's. Last month I created a new butterfly identification page for my personal website, using PHP and SQLite. By choosing some colors and patterns, newbies (in the butterfly field) can identify any butterflies they may have seen in the field. The page worked well on my desktop but when I uploaded it to Tripod, I realized that they support only Perl and not PHP. So I decided to convert the PHP page to Perl, without having to recode it from scratch. I started by making a copy of the ".php" file and renaming it to ".cgi". Then I made the below changes to convert the PHP code to Perl. Hope these tips would be useful to someone who reads this post.

* Added the Perl shebang line at the top of the page
* Added the standard line to print the content type
* Enclosed all other HTML code within multi-line prints
* Replaced all instances of the PHP "echo" with the Perl "print"
* Replaced the database connection PHP code with the corresponding Perl code
* Replaced the database query PHP code with the corresponding Perl code
* Added a subroutine for getting the CGI parameters, something that PHP automatically did
* Replaced the PHP built-in hash "%POST" to the hash "%form" created by my subroutine
* Replaced the square brackets used for PHP hashes with the curly brackets used in Perl
* Removed the single or double quotes that were used to reference the hash values in PHP
* Replaced the not equal to operator "<>" of PHP with the Perl equivalent "ne"

P.S.: After all that hard work, I found that Tripod does not support the use of DBI.pm. So finally I had to replace the dynamic butterfly identification page with an XML-XSLT page where the readers have to look at a table giving colors and patterns to try and figure out which butterfly they had seen. Well, such is life!

Tuesday, August 13, 2013

Tips on Converting Python-CGI to Perl-CGI

Last month I created a new feedback page for my personal website, using Python. It worked well on my desktop but when I uploaded it to Tripod, I realized that they support only Perl and not Python. So I decided to convert the feedback page to Perl, without having to recode it from scratch. The groundwork for this took some time, as I had to install Active Perl and brush up my Perl knowledge by tweaking a few old Perl-CGI scripts. Today I created a copy of the CGI script and made the below changes to convert it from Python to Perl. Hope these tips would be useful to someone who reads this post.

* Converted the shebang line from #!/Python27/python to #!/Perl/bin/perl
* Added a semi-colon after every line of Python (now Perl) code
* Added a $ sign before every Python (now Perl) scalar variable
* Converted the multi-line prints from Python format (print """) to Perl format (print <<HTML)
* Removed the Python import line for "sys"
* Removed the Python import line for "time". Used Perl's localtime() function to get date and time
* Removed the Python import line for "cgi". Used a downloaded Perl code snippet to get the CGI parameters, choosing  one that takes care of both GET and POST parameters
* Converted the Python "if-elif-else" syntax to the equivalent Perl "if-elsif-else" syntax
* Converted the Python "try-except" code for opening a text file to the normal Perl file opening code, as Perl does not currently support "try-except"
* Converted the single-line file open and read code of Python to the equivalent Perl code
* Converted the Python syntax [filename.write("abc")] for writing to text file to the equivalent Perl syntax [print FILENAME "abc"]
* Replaced Python's text concatenation operator "+" with the equivalent Perl operator "."
* Removed Python's str() function, as Perl automatically takes care of converting variables based on the context
* Ensured use of "eq" operator instead of "==" operator in "if" conditions involving string variables

Tuesday, July 30, 2013

Introduction to SharePoint

A part of our Projects team has been spun off into a SharePoint team, which will adapt and implement a particular CRM template for Indian as well as overseas customers. Since our architect is also a part of this new team, he was able to provide some Web links to help me understand what SharePoint is all about

Microsoft SharePoint is a Web application platform. Simply put, it is a tool to store, to manage and to retrieve information. This information could be text or MS Office documents or other files, like videos. The main strength of SharePoint is that even non-technical users can use it as well as develop applications using it

Initially, SharePoint was used for content management and document management on Intranets but recent versions are much more powerful. You can use Sites to store and manage information, and share it on the Intranet or Internet. You can use Communities to collaborate with colleagues. You can use Content management, including integration with your existing Microsoft Office documents. Search allows you to retrieve information quickly and to find people within your organization. Insights allow you to effectively obtain information stored in a different repository, within a certain useful context. SharePoint enables no-code integration of data, documents and processes to create Composite applications

The most basic element in SharePoint is an Item (calendar entry, task, contact) or a Document (Word, Excel, PDF). Both Items and Documents can have metadata associated with them. They can be arranged using Folders

Items are stored in Lists while Documents are stored in Libraries. A List or Library uses Views to display information. VIews depend on context but the standard view is as rows and columns. Each row represents an Item or Document while its metadata is displayed in the columns. Metadata can be grouped into Content Types

Each List or Library is part of a Site, which is a container for data. Sites can be Team Sites, Project Sites or Internet Web Sites. They can be arranged in hierarchies and collected into Site Collections with a Root Site at the top and common site settings. Each Site has a default page (Homepage), along with various other Pages

Sites are viewed using a web browser. Hence there are Web Applications, which can contain several Sites or Site Collections and are hosted on Web Servers. Multiple SharePoint servers can be grouped into a Sharepoint Farm

In short, SharePoint provides a solution to all your information management needs with a secure and remote access. Andreas Glaser's website provides some good SharePoint tutorials that are very useful for beginners. Note that the content of this post has been adapted from his pages, and the SharePoint Wikipedia page

Friday, April 26, 2013

Introduction to SQLite

Our Product Development team has started the architecture and design process of an app for Android phones, which uses SQLite as a critical part of the app architecture. Since this was a new technology for both our architect and myself, I decided do some reading on the Web so that I could help him in the detailed architecture and design activities

Basically SQLite is an RDBMS that fits into a small file and exists as an integral part of a client application (unlike other RDMBS that exist as separate "database servers"). At the same time, it supports terabyte-sized databases and gigabyte-sized strings and blobs. The SQLite website calls it "a software library that implements a self-contained, serverless, zero-configuration, transactional SQL database engine". It also claims that SQLite transactions "are atomic, consistent, isolated, and durable (ACID) even after system crashes and power failures"

The website also claims that "SQLite is the most widely deployed SQL database engine in the world". The reason is not hard to see, as "SQLite is popular choice for the database engine in cellphones, PDAs, MP3 players, set-top boxes, and other electronic gadgets". Also, since "it requires no configuration and stores information in ordinary disk files, SQLite is a popular choice as the database to back small to medium-sized websites". SQLite is used by major corporations ranging from Adobe to Mozilla and Airbus to Toshiba

Wikipedia tells me that "D. Richard Hipp designed SQLite in the spring of 2000 while working for General Dynamics on contract with the United States Navy" and also that "SQLite implements most of the SQL-92 standard for SQL but it lacks some features. For example it has partial support for triggers, and it can't write to views". SQLite "is weakly typed in some of the same ways that Perl is: one can insert a string into an integer column (although SQLite will try to convert the string to an integer first, if the column's preferred type is integer)"

Writing PHP code for SQLite is simple, as PHP has the SQLite3 library pre-installed but it has to be enabled by uncommenting two lines in the PHP.ini file:
 extension=php_pdo_sqlite.dll
and
 extension=php_sqlite3.dll

Here are some simple lines of code for manipulating an SQLite database using PHP:
<html>
 <head>
  <title>PHP with SQLite</title>
 </head>
 <body>
  <h2>Testing PHP with SQLite</h2>
<?php
#Create or open SQLite database
$db = new SQLite3('mysqlitedb.db');

#Create table if it doesn't already exist
$db->exec('CREATE TABLE foo (bar STRING PRIMARY KEY)');

#Insert row in table or replace existing row
$db->exec("INSERT OR REPLACE INTO foo (bar) VALUES ('This is a test')");

#Read data from table and display it
$result = $db->query('SELECT bar FROM foo');
while ($row = $result->fetchArray()) {
print ("Value of <i>bar</i> in table <i>foo</i>: " . $row["bar"] . "<br>");
}
?>
  <br>
  <a href="index.php">Back</a>
 </body>
</html>

Wednesday, April 17, 2013

What is Software Architecture?

Today the architect in my team asked for my help in documenting the architecture of a new application. Since my experience of software architecture (or what I understood by that term) was so far restricted to participation in design discussions and creation of functional diagrams (System Overview) and technical diagrams (Database Design), I decided to understand what Software Architecture actually means. So I read some articles and blogs on the Web and noted down some of the interesting things they had to say (links embedded in this post, copyrights hereby acknowledged)

According to an article on MSDN, "Software application architecture is the process of defining a structured solution that meets all of the technical and operational requirements, while optimizing common quality attributes such as performance, security, and manageability. It involves a series of decisions based on a wide range of factors, and each of these decisions can have considerable impact on the quality, performance, maintainability, and overall success of the application."

In this definition of software architecture, Microsoft mentions both technical and operational requirements. But some authors, such as Patrick Kalkman in a Software Architecture Design article on CodeProject, aver that software architecture should focus on the non-functional requirements of the stakeholders, instead of being based on purely technical motives

An article on IBM developerWorks defines software architecture as per the IEEE Standard 1471-2000, the IEEE Recommended Practice for Architectural Description of Software-Intensive Systems, commonly  referred to as IEEE 1471. Thus "Architecture is the fundamental organization of a system embodied in its components, their relationships to each other, and to the environment, and the principles guiding its design and evolution." [IEEE 1471]

As per the IBM article, the standard also defines the following terms related to this definition:
  • A system is a collection of components organized to accomplish a specific function or set of functions. The term system encompasses individual applications, systems in the traditional sense, subsystems, systems of systems, product lines, product families, whole enterprises, and other aggregations of interest. A system exists to fulfill one or more missions in its environment. [IEEE 1471]
  • The environment, or context, determines the setting and circumstances of developmental, operational, political, and other influences upon that system. [IEEE 1471]
  • A mission is a use or operation for which a system is intended by one or more stakeholders to meet some set of objectives. [IEEE 1471]
  • A stakeholder is an individual, team, or organization (or classes thereof) with interests in, or concerns relative to, a system. [IEEE 1471]

The IBM article further lists the core characteristics of software architecture as follows:
  • An architecture defines structure
  • An architecture defines behavior
  • An architecture focuses on significant elements
  • An architecture balances stakeholder needs
  • An architecture embodies decisions based on rationale
  • An architecture may conform to an architectural style
  • An architecture is influenced by its environment
  • An architecture influences team structure
  • An architecture is present in every system
  • An architecture has a particular scope

Finally, going back to the first line of this post, you may want to ask if the "architect" in my team is really one, or just a senior software developer who is more involved than other team members in the design process. An article by Simon Brown offers the answer to this question.

Friday, March 15, 2013

5 Must-dos for Recovering Failed Projects - by Shoaib Ahmed

Can't resist re-posting this recent blog post from another Project Manager (with some edits by me), as it more or less reflects my own thoughts on the subject. I have given his name in the title and the link to the original blog post at the bottom of the page. I hope these would be enough by way of acknowledgement

How can one rescue a failed project? What are some of the things that need to happen before you can achieve any improvement?

Acknowledge the failings
When doctors treat patients with substance abuse, the first thing they try to instill in the patients is the acknowledgement that a problem exists. The environment around failed IT projects is exactly the same. It lurches from one problem to another while trying to apply band aids to keep things going. Until parties are willing to admit that problems exist, there is no hope for a resolution. If you keep doing the same things, there is no chance of the result being any different than what it is today. It is very likely that some within the project saw the train wreck coming and may even have voiced it. Seek those out to understand what went wrong.

Divorce emotional investments
One of the basic practices of IT is that software developers do not test their own code. It is not because they are not capable. In fact, they should be more capable than anyone else. However, as human beings we are predisposed to not finding holes in our creation. Same is true for the management of a project. The current status is a reflection of many decisions taken through the course of the project. Many in the management will feel the decisions were correct at the time with the information they had at hand. You need to remove the management decision makers from both the supplier and customer to ensure progress. Leaving them intact will risk required changes not happening

Aim for small wins
In a major failure it may sound counter intuitive to look for small wins, as the problem is a sizeable one. Most adults are reasonably sensible and not easily taken in by bulls**t. They are well aware that a major failure is not going to be resolved quickly. What you need to achieve at all costs is some confidence among your user base that improvements are underway and they can see a light at the end of the tunnel. Bigger your ambition is, more balls are in the air and higher is the chance of it all coming crashing down because of weak foundations. Identify how you are looking to improve, set target of small improvements and communicate honestly.

Throwing more resources is not always the answer
As Fred Brooks Jr has pointed out, the most reliable software is written by one or two man bands. The need for quicker output requires many more developers and as a result introduces complexities several fold. One of the major reasons projects fail is because communication is poor. Having large teams working on the recovery attempt is therefore more risky than the original project. It is a common tendency in projects to throw more resources at a problem. That is just about the worst things you can do in a failed project. With smaller wins, go for smaller teams.

Be prepared to abandon the project
For all the best will in the world, sometimes you will not be able to retrieve failed projects. Cost of retrieval may be higher than doing another project from scratch. It also may not give you the benefits you were after  because of the additional cost. You may find that there is more political will to spend in trying to fix something than re-doing it correctly or abandoning it. Be careful not to be seduced by that. A fully functional  replacement system that does 90% of the requirements may be better than an error prone system designed to deliver all of the requirements.

Link: