I have been doing programming as a consultant a little over a year and half. While working last year, I realized that there are a couple attitudes that most consultants have that I think all programmers would do well to adopt, or at least think about.
* First off, make sure your code is written in such a way to be easily readable and well-commented. The programmer reading the code and trying to figure it out 6 months later may be you! This will also made the code easier to maintain and debug.
* Document as you go. This relates to the previous point. There's never time to document a project after it is done, but if you do a few minutes a day as you are developing, it won't be so bad.
* Keep an ongoing list of features you want to add and bugs you want to fix.
* Realize you won't be working on any specific program forever. You should have a plan for handing the work you've done off to someone else. People get promoted, transferred to other projects, get better jobs, get laid off, and sometimes get hit by a bus (see last item).
* Always make sure you are learning new things and coming up with ideas on how to do things better.
* Know who your customer is & be sure your work is serving them. As a consultant, your customer is your client. As an employee, your customer is your employer, your boss, or whoever is going to be the end user of the program you are creating.
* Last of all: everyone says you should document things & share information so if you get hit by a bus, people will know what they need to know to continue the project. This point is brought up often enough, programmers should generally just avoid buses, just to be safe. Take the subway or train instead. No one talks about programmers being hit by them.
Thursday, January 29, 2009
Friday, November 21, 2008
Perl references to return values
Today I was working on some Perl code that needs to take an array returned from one function, make a reference to that array, and pass the reference to another function. It seemed like a simple enough thing to do. I've been doing Perl programming for seven years. After trying a few things and hitting failure, I pulled out the O'Reilly book Programming Perl and read the chapters on references and on subroutines. You can make references to anything: scalars, arrays, file handles, subroutines. But it seemed you can't just take a sub-routine's return value and make a reference to it.
A little poking around on Google turned up an indication that I'm not missing something. There may not be a way to do exactly what I'm trying to do according to a post on Perlmonks.org. So instead of making a reference to a sub-routine's return value, you have to make a reference to a copy of the return value.
Here is the code that demonstrates this:
A little poking around on Google turned up an indication that I'm not missing something. There may not be a way to do exactly what I'm trying to do according to a post on Perlmonks.org. So instead of making a reference to a sub-routine's return value, you have to make a reference to a copy of the return value.
Here is the code that demonstrates this:
#!/usr/bin/perl
#From a post on caffeinemakesmesleepy.blogspot.com
# Demonstrate how to take an array return from one function and pass a reference to it into another.
#[] around return_array function makes a reference to a copy of the return value of that function.
# you need the () after return_array or "return_array" gets passed into take_array_ref
take_array_ref([return_array()]);
sub return_array {
my @ret;
push (@ret, 'FOO');
push (@ret, 'BAR');
return @ret;
}
sub take_array_ref {
my $ref = shift;
my $i = 0;
foreach my $value (@$ref) {
$i++;
print "Element #$i: $value\n";
}
}
Saturday, October 25, 2008
Perl Test::More trick
Recently I was working on a rather large Perl module and writing unit tests for it. I had some tests already completely done and trying to debug another chunk of code & tests. It was hard with debugging on to see what was going on. I just wanted to see one set of tests and nothing from the other sets. At first I commented out the blocks of code that ran the tests I didn't care about. Then I realized there was an easier way.
Say you have a test that starts with something like:
Easy way to disable these: turn the above line to something like
When you do run_tests() on this test module, it won't run this block of tests because this function will no longer register as a test.
NOTE: this tip assumes you are using Test::More and Test::Class and have it set up so all your tests are in a module and you have a script that loads that module and does ->run_tests on the module with your tests.
Say you have a test that starts with something like:
sub my_batch_of_tests : Test(6) {
Easy way to disable these: turn the above line to something like
sub my_batch_of_tests { # : Test(6)
When you do run_tests() on this test module, it won't run this block of tests because this function will no longer register as a test.
NOTE: this tip assumes you are using Test::More and Test::Class and have it set up so all your tests are in a module and you have a script that loads that module and does ->run_tests on the module with your tests.
Wednesday, October 1, 2008
SQL - you can't compare NULL to anything
Here is a little mind-bender for any of you who are programmers who routinely work with SQL. Write a little code that checks to see if NULL equals NULL. It returns false. Now write code to see if NULL is not equal NULL. It will return false too. Now repeat with NULL and any value. NULL equals 42 returns false, NULL is not equal 42 returns false. * What in the world is going on here?
Here's what I found when I ran into this issue before. What we're seeing here is the impact of NULL being a mathematical concept. SQL is built on many mathematical concepts. The concept of NULL is an unknown value. Since NULL is an unknown value, it may be 42, it may be Fred. We simply don't know. So comparing anything at all to NULL (even comparing NULL to itself) will *ALWAYS* return false. This is why you need to specify IS NULL or IS NOT NULL if you want to see if something is or isn't NULL.
* I experienced this issue most recently working with Oracle, but it will work with any SQL database such as MySQL, PostgreSQL, and Microsoft SQL Server.
Here's what I found when I ran into this issue before. What we're seeing here is the impact of NULL being a mathematical concept. SQL is built on many mathematical concepts. The concept of NULL is an unknown value. Since NULL is an unknown value, it may be 42, it may be Fred. We simply don't know. So comparing anything at all to NULL (even comparing NULL to itself) will *ALWAYS* return false. This is why you need to specify IS NULL or IS NOT NULL if you want to see if something is or isn't NULL.
* I experienced this issue most recently working with Oracle, but it will work with any SQL database such as MySQL, PostgreSQL, and Microsoft SQL Server.
Labels:
database,
mathematics,
null,
oracle,
programming,
sql,
tricky
Friday, September 5, 2008
Using Windows environment variables
This post will be a little more basic than most things I write here. I'm used to using MacOS/X on the desktop and Linux on the server side. So when I have to use Windows for one reason or another it sometimes takes me a bit to figure things out.
Today I was helping a co-worker with Oracle Application Express (APEX for short) and the install directions said to run "cd $ORACLE_HOME/apex" and then run some commands. The cd command didn't work because Windows does environment variables different than Unix operating systems.
This article covers it in more detail but in short Windows indicates environment variables by putting a % (percent sign) before and after the variable. Variables are not case sensitive.
You can show them by running "echo %ENV_NAME%" and set them on the command line by running "ENV_NAME = new_value". You can make the setting part of your login profile by right-clicking on "My Computer", then click Properties, then Advanced, and then Environment Variables. This is for XP, the location may be different on Vista or other versions of Windows.
Today I was helping a co-worker with Oracle Application Express (APEX for short) and the install directions said to run "cd $ORACLE_HOME/apex" and then run some commands. The cd command didn't work because Windows does environment variables different than Unix operating systems.
This article covers it in more detail but in short Windows indicates environment variables by putting a % (percent sign) before and after the variable. Variables are not case sensitive.
You can show them by running "echo %ENV_NAME%" and set them on the command line by running "ENV_NAME = new_value". You can make the setting part of your login profile by right-clicking on "My Computer", then click Properties, then Advanced, and then Environment Variables. This is for XP, the location may be different on Vista or other versions of Windows.
Saturday, June 7, 2008
MySQL++ meets Leopard on an Intel Mac
A friend of mine is learning C++ and also wants to learn MySQL. I decided to go ahead and show him how to connect MySQL to a database in C++. Once I started, I realized I've never done this with MySQL, only with PostgreSQL. Oh well, how different could it be???
I decided to install on my Mac Mini which is running MacOS/X 10.5 Leopard. Installing the latest stable version of MySQL from source was cake. I got the sample C program working with no problems and then I looked for how to hookup C++ to MySQL. MySQL itself does not come with a C++ API, only C. The C++ bindings are provided by a project called MySQL++. This is when the problems started.
First off, it gave me some errors about not being able to find some functions. This was the actual error:
A little googling around turns up this message on the MySQL++ mailing list. Apparently the way things were coded, this "max" function works perfectly fine on 32 bit processors, but not 64 bit. The fix is to change 1 line of the lib/mystring.h file in the source from "typedef unsigned int size_type;" to "typedef size_t size_type;". It sounds like this fix will be in the next release of MySQL++ and then no one will have to worry about it.
Another note here - the library for MySQL++ isn't libmysql++ or mysql++ as one may expect. It is mysqlpp. Just as well, special characters tend to mess things up sometimes.
The other problem I ran into was this error when trying to compile the sample program from the MySQL++ documentation:
This turned out to be one of those silly mistakes that causes a big problem. In specified the linker path, I had put
-L /usr/local/lib
When I changed it to
-L/usr/local/lib
it worked fine. This seems like something the GNU development utilities should be able to be smart enough to handle.
I decided to install on my Mac Mini which is running MacOS/X 10.5 Leopard. Installing the latest stable version of MySQL from source was cake. I got the sample C program working with no problems and then I looked for how to hookup C++ to MySQL. MySQL itself does not come with a C++ API, only C. The C++ bindings are provided by a project called MySQL++. This is when the problems started.
First off, it gave me some errors about not being able to find some functions. This was the actual error:
./lib/mystring.cpp: In member function ‘int mysqlpp::String::compare(const std::string&) const’:
./lib/mystring.cpp:67: error: no matching function for call to ‘max(unsigned int, size_t)’
./lib/mystring.cpp: In member function ‘int mysqlpp::String::compare(const char*) const’:
./lib/mystring.cpp:81: error: no matching function for call to ‘max(unsigned int, size_t)’
./lib/mystring.cpp: In member function ‘int mysqlpp::String::compare(const std::string&) const’:
./lib/mystring.cpp:67: error: no matching function for call to ‘max(unsigned int, size_t)’
./lib/mystring.cpp: In member function ‘int mysqlpp::String::compare(const char*) const’:
./lib/mystring.cpp:81: error: no matching function for call to ‘max(unsigned int, size_t)’
A little googling around turns up this message on the MySQL++ mailing list. Apparently the way things were coded, this "max" function works perfectly fine on 32 bit processors, but not 64 bit. The fix is to change 1 line of the lib/mystring.h file in the source from "typedef unsigned int size_type;" to "typedef size_t size_type;". It sounds like this fix will be in the next release of MySQL++ and then no one will have to worry about it.
Another note here - the library for MySQL++ isn't libmysql++ or mysql++ as one may expect. It is mysqlpp. Just as well, special characters tend to mess things up sometimes.
The other problem I ran into was this error when trying to compile the sample program from the MySQL++ documentation:
ld: in /usr/local/lib, can't map file, errno=22
collect2: ld returned 1 exit status
This turned out to be one of those silly mistakes that causes a big problem. In specified the linker path, I had put
-L /usr/local/lib
When I changed it to
-L/usr/local/lib
it worked fine. This seems like something the GNU development utilities should be able to be smart enough to handle.
Thursday, June 5, 2008
Tortoise SVN for Windows tips
I just figured out two new features in Tortoise SVN today. First off, you can get SVN info showing up in Windows Explorer.
1. Go to a folder that contains files you checked out from SVN. Go to View -> Details
2. Right click on any column to get a list of available columns.
3. Select "More" and scroll down until you get to the list of "SVN" details. I highly recommend SVN Status & SVN Revision.
4. Click OK and then refresh the window. You'll have SVN status & revision # on all the files in the folder controlled by SVN.
5. (Optional) Go to Tools -> Folder Options and click the View tab. Hit Apply to All Folders & you'll have this same view for all folders next time you open them.
Trick #2.
1. Open up TortoiseSVN settings & go to "General".
2. Click on the "Set filedates to the "last commit time"
3. Hit Apply & then OK.
Your files from SVN will now show the last time you committed them as the modification time. One note here: this didn't seem to work for me until I deleted my files from my SVN working copies & checked them out again.
1. Go to a folder that contains files you checked out from SVN. Go to View -> Details
2. Right click on any column to get a list of available columns.
3. Select "More" and scroll down until you get to the list of "SVN" details. I highly recommend SVN Status & SVN Revision.
4. Click OK and then refresh the window. You'll have SVN status & revision # on all the files in the folder controlled by SVN.
5. (Optional) Go to Tools -> Folder Options and click the View tab. Hit Apply to All Folders & you'll have this same view for all folders next time you open them.
Trick #2.
1. Open up TortoiseSVN settings & go to "General".
2. Click on the "Set filedates to the "last commit time"
3. Hit Apply & then OK.
Your files from SVN will now show the last time you committed them as the modification time. One note here: this didn't seem to work for me until I deleted my files from my SVN working copies & checked them out again.
Labels:
developers,
programming,
source code control,
subversion,
svn,
tortoise svn,
windows
Subscribe to:
Posts (Atom)