MSDN . MSDN Library . Visual Tools and Languages . Visual Foxpro
I spent most of the day talking and working with a telecom technician who works for a company that provides spanking fast DSL internet connection.
That is if 'spanking fast' is defined as the urge to apply a quick blow in the arse to the person next to you every time you get annoyed with the speed. But seriously it is faster than my 56K dial-up internet connection at home.
I even had the chance to ride on their service mobile and talk about life with him, talk about food, the sea and raising children. He accompanied me to a computer hardware retailer, gave me a discount after the owner allowed us to test the component first before even paying for it.
Sometimes we often hear the word 'sucks' being added to something. Company-001 sucks. TechBlahBlah sucks.
The world sucks.
Most often we add this word because we're dissatisfied... or probably because seeing the negative side is inherent to our human traits.
And we do this without even considering the reasons behind such thing.
This technician (I won't name names nor I would name the company since I don't like saying negative stuff to a Philippine-based company even if it is already owned by a foreign entity), works with his partner (yup just the two of them) servicing 100++ (or even greater) clients covering an area which is nTechnicians(raised to the power of 32(square miles)).
The company holds N number of employees nationwide five years ago, now they're down to N/4 and N here is a five digit number having a val(substr(alltrim(str(N)), 2, 1)) > 6. They're even planning to trim down even more.
Indeed... it is a sucky world out there.
But there's nothing we could do to improve things by re-stating the obvious.
One must unload(TheSuckinessState).
There are tons of ways really.
But none of them includes including the word 'sucks' in anything that disappoints a first person's pathetic self centered soul.
Code Dump: the time where you take a break from your programming related tasks to talk about your programming related tasks.
In PROJECT::SOPHIEAI (IUMS: Internet Usage Monitoring System), USAGE.dbf holds the records that stores the log-in/log-off information of the users of a certain internet lab/cafe at a given time and space. Along with the IDNO number of the user of course and some other fields.
Violating the second rule of normalization (or was it the third rule), I also included the TotalNumberofHoursUsed per usage and the TotalFee paid.
If you follow strictly the normalization rules, you know that you don't have to include in the database fields that can be derived from two or more fields that are already in the database.
For example if your database has fields named Field01 and Field02 with sample values 10 and 618 respectively, you don't need a Field03 which will store 628, the total of Field01 + Field02. Normalization rule will then call you moronic and consider you an outcast of the database programming world.
You deserve to be eaten alive by vultures.
You deserve a punishment such as watching Barney re-runs again and again.
But in some cases, yes... believe me... there are times when you have to violate and override this rule. These are the cases when speed-related principles are far more important. Plus... considering that these days hard disk space is getting cheaper and time (since Mida's era) is constantly gold, it justifies the normalization override process.
So back to PROJECT::SOPHIEAI.
Now because of some 'outside factors' (again), I need a patch that would make a different database, CRED_NET.dbf, which holds the fields TimeLeft and Credit be synchronized with the data USAGE.dbf holds.
Let's say USAGE.dbf records for student 0001 are (let's just take the important fields for discussion):
Now CRED_NET on the other hand holds how much is left for a student 0001. There are instances when the values on both databases don't synchronize. Yes the existence of these databases violate the normalization rule once again but you have read the reasons above already, right?
And can you stop reminding me about normalization rules so we can go on?
So to correct things you execute this untweaked patch (I'll call it the 'brute force approach'... 'Brute'... like 'Brute Lee')
select CRED_NET set order to CCRENAME do while not eof() cIDNO = alltrim(CRED_NET.IDNO) **' ···································· **' SECTOR.007.BEGIN select USAGE set order to CUSAIDNO go TOP do while not eof() if alltrim(USAGE.IDNO) == cIDNO cTimeCount = TimeCalc(cTimeCount, USAGE.TIMETOTAL, 1) nCreditsTotal = nCreditsTotal + USAGE.FEENET endif skip enddo **' ···································· **' SECTOR.007.END select CRED_NET cTimeReflect = TimeCalc(cTimeCount, '40:00:00', 2) nCreditsReflect = 800.00 - nCreditsTotal rlock() replace CRED_NET.TIMELEFT with cTimeReflect replace CRED_NET.CREDIT with nCreditsReflect unlock skip enddo
The above code works... of course, but... like any process in this world that involves brute force, it is slow.
Now replace the SECTOR.007 part of the code above with this:
set order to CUSAIDNO
set filter to alltrim(USAGE.IDNO) == cIDNO
do while not eof()
cTimeCount = TimeCalc(cTimeCount, USAGE.TIMETOTAL, 1)
nCreditsTotal = nCreditsTotal + USAGE.FEENET
You'll see a HUGE difference in terms of execution speed.
TimeCalc is a function by the way that adds, substracts, multiplies and divides two time variables. Something which I'll post later. (You can find the basic/raw version inside the Microsoft Help and Support Site though),
Of course when you're doing these kinds of patches, don't forget the progress bars. It is a good hypnotic-mechanism for the users to develop this affinity for your software.
Now back to work.
Foxpert: Security in FoxPro (Protecting Application and Data). With the advent of tools such as ReFox and UnFoxAll, this whitepaper is a must read. But it includes more topics aside from these decompilers mentioned.
I think, fundamentally, open source does tend to be more stable software. It's the right way to do things. I compare it to science vs. witchcraft. In science, the whole system builds on people looking at other people's results and building on top of them. In witchcraft, somebody had a small secret and guarded it -- but never allowed others to really understand it and build on it.
West Wind Internet Protocols 4.55 (wwIPStuff) released. The class library supports the following:
- SMTP and POP3 Email support
- HTTP - Access Web content from VFP
- Advanced HTTP support
- FTP - Transfer files
- Low Level Socket Access
- Dial up Networking
- IP Address validation
- Fast C based Conversion Routines
Along with that release, is an insightful article: Why West Wind Html Help Builder is NOT a .NET Application.
I'm days behind linking this... Ken Levy posted the August 2004 Visual Foxpro Newsletter which contains a FAQ that answers some of VisualFoxpro-related issues.
So let’s get real. Bad programmers write bad code. Good programmers write good code. RAD lets bad programmers write bad code faster. RAD does NOT cause good programmers to suddenly start writing bad code.
If you can remember, a couple of months ago he enumerated why he refrains from blogging. How I wish those unmovable-arse humans I convinced to blog would also have a change of mind.
While reading Wesner Moise's blog (.NET Undocumented, one of the first blogs I subscribed to), I found out that KurzweilAI.net now has an RSS feed. I 'HTTrack-ed' that site before when I found some very very interesting AI-related articles.
If you are using the HTML version of that site and can't seem to find the syndication feed link, here's a direct link to the rss feeds.
More and more programmers who are using VisualFoxpro are coming out in the blogosphere. Here are two links that I have discovered just recently: Craig Bailey and Andrew Coates (not entirely VFP but he mentions VFP once in awhile).
I wonder if it is just me still getting used to waking up around 4AM (I usually sleep around 3AM) or my FireFox browser, that makes the OZ 2004 Speaker section scramble the names and the pictures. It works fine on the IE6 browser though.
Here are some alternative programming fonts. Nice... thanks Vernon Labayog for that link.
What a way to start a blog.
QS and I had a difficult day. Although our problems are unrelated and we're not up against each other, still it doesn't remove the fact that crap happens.
But let's look at the good side of things... at least she's blogging once again.
Although I do enjoy freelance software development very much, it doesn't remove the fact that outside factors come in the way. These outside factors are often used to blame the programmers for every problems popping out of this world.
The user is using the program you created, sidetracked and visited a spyware/trojan-infested site, crashed the computer and spread the worm in the local network, eradicated his documents, impaired the OS which in turn hangs the program.
Guess who they're blaming?
They blame the programmer and his Level42 idiot-proofed database application.
Of course this is just the simplest variation of certain problems a freelance developer encounters. I could go on and on enumerating them all.
Yes... 'freelance software development' may sound sweet to one's ears, yet... it holds a lot of risks too.
While in a non-freelance software business, clients and some users tend to blame 'the company' for any other outside related bugs too, the developers have a better shield. In fact, some are even protected with seven headed salivating bulldogs guarding the programming zone.
While in worst cases, notorious (or shall we use 'careless' to be less harsh) programmers get fired or castrated, you seldom see them being blamed directly by users or clients. Experts would even sometimes blame the marketing department or the head for enslaving these borgs in four-sided cubicles.
You don't see 'the programmer Mr. Anderson coded this bug, redirect your hate mails to his email' lines in support forums and company websites.
In some cases, it is the support telephone entities that receive these kind of 'attacks'. Or the project heads who would professionally protect his team and defend his programmers to the last 8-bit of his blood
In the freelance world you're on your own. You are responsible for the un-released memory-based variables you make that cause your program to crash the OS. You see unchecked bugs unfold before your eyes while you are presenting the program to your clients. You hear their problems directly. You interact with them. You feel their pain from using your 'Duh-I-thought-I-solved-that-already' programs.
You are responsible. No shields or bulldogs to protect you. You're on your own.
But you do learn and grow.
Not that difficult really if the problem lies on the code or the 'logistics' of the program.
A lot harder when the problem lies on the users' attitude, in the way they view computers, in the way they view life.
And a helluva-lot harder when you don't know what really caused the problem.
Add the fact that your name is always on the line.
In the world of freelancing, if there's one thing you have to hold dear and hold it dearly like it's a 1024K halo-blue-ish diamond found behind the galactic borders of the Andromeda Galaxy only every 1168 lunar cycles... that would be your name... your reputation.
Yes... your reputation.
It can make you or break you.
What's worse is when your name and reputation is on the line because of the things you don't do. Because of the 'outside factors'.
The blasted 'outside factors'.
But like any other thing this world holds, it's how you handle these things that counts.
And that too could make and break you.
But whatever happens... life goes on... and still, shit happens.
After-blog dangling references:
I'll keep you updated on this problem and will make things less abstract once I have a full grasped of what the cause of the problem really is.
3AM and I'm done wrapping up paper plans for tomorrow's client visit. Make that later this day.
ADTX SYSTEMS (formerly APTI) is in need of programmers. My former classmate works in that company and she told us that they need at least 50 'coders' immediately (ASAP).
That's a large number of borgs... quite scary if you'd ask me.
And considering she did used the words 'immediately' and 'ASAP' in one e-mail, it means something.
They're looking for Java Programmers (AD 04-007), Microcode/Firmware Engineers (AD04-008) and Device Driver Engineers (AD04-009).
Interested applicants are invited to send their resume, transcript of records and recent 2x2 picture to the address below stating position code:
ADTX Systems, Inc.
c/o Human Resources Department
3/F Multinational Bancorporation Centre
6805 Ayala Avenue, Makati City
Tel Nos: +63 (2) 889-5070 | +63 (2) 845-3875-77
Fax No.: +63 (2) 889-1800
E-mail: jobs [at] adtxsystems [dot] com
Or you can e-mail my classmate: beng [at] adtxsystems [dot] com. Doing so will help her and her co-programmers regain the sleep they're missing these days.
On a different frequency, Avatar posted some FireFox-related hacks.
I received an e-mail from one of my college classmate who was also my officemate when I was still working in Davao. He told me that the database project we created 6 years ago was still pretty much alive.
Although I was only an assistant programmer in that project and it was Jerry who did most of the job, still... it is nice to know that the project we dubbed as BRAINS (Budget Resource Allocation Information System) is still being used.
It was also the first database application we developed after being freed from the cruel college un-ending digital chains and thorns. You know... the kind of situation that resembles the code below:
for i = 1 to nInfinity
SetDeadline(nTime = short, lRidiculous = .T., lMovable = .F.)
SetMind('They will work on the last minute anyway... so...')
AddLoad(tracks(Philo, 16) + tracks(Theo, 16) + tracks(English, 24))
**' Exit statement removed
BRAINS was developed in VisualBasic.
Yes, I know lambasting VisualBasic is one of my favorite past times but I do have great respect for it when it is properly and intricately woven.
My friend, Jerry Flores knows this language very well.
He breathes VB.
He handles database normalization to the core.
How about we hear a blog from you, Mr. Jerry 'VB Guru' Flores?
Beakman also uses VisualBasic with ADO and SQL very well. The works he's been putting on his Digital Nervous System is quite remarkable.
Although it was mentioned countless of times already that VB.NET != VB6 and it is not even fully backward compatible, VB.NET addresses most of the issues that were used to criticize the Visual Basic language.
But still, VisualFoxpro is my main artillery; there are just some matters that pushed me to delve more into SQL Server and ADO programming.
Something which I would probably share later.
I had a weird dream last night.
Ah... all dreams are weird so that's data redundancy already.
Anyway... in my dream, Linus Torvalds and Bill Gates were playing chess in a park. The ambience was even in 3D... surreal 3D to be precise, sort of a distorted 3D-like environment quite close to Pixar's animated chess clip, Geri's Game.
(Speaking of Pixar, check out this latest Incredibles trailer.)
But this dream's more darker... and more violet-ish.
Probably Steve Jobs is behind all these 'Microsoft versus Linux games', eh? Sounds like an interesting conspiracy theory.
But no, this isn't about conspiracy theories... this is about my dream.
Besides, Steve doesn't give an iMice arse about this, he's too busy on his 'chameleonic computer', you know a Mac whose shell can change colors, or the second Japan Apple store opening or the rumored Apple TabletPC.
There... wandering again... back to the dream.
I can't remember everything but there was a point in that dream when Linus was taunting Bill... 'You can't beat me, I've been playing this game since I was still a kid, when I was in beta version. My linux shell commands and libraries naming convention are even inspired by the way chess moves are recorded.'
Bill replied, 'Are you familiar with the Windows BSOD? It has VxD written all over it.'
I can't remember who won that game or how the dream ended. But I do remember it shifting places where the next 'scene' involves a half cyborg rabbit.
Speaking of chess, the 14th Abu Dhabi International Chess Festival is being held from August 14 to August 24, 2004. One of its main highlight is the 'Clash of The Computer Titans' which features the multi-champion Shredder against the Linux-powered Hydra.
Yes... I think humans grew tired of watching those human versus machine chess tournaments (or probably the human versus human battles) already that they're firing up these machine versus machine tournaments.
Creating a program that do those chess-move-analysis computation I know is an ultimate milestone for humans, but if you'd ask me I still think it is the uber-most-geek-iest way of having an excuse not to play the game.
An excuse not to think which is ironic because humans need to think.
I know... I know... creating such program involves a lot of thinking. But there is a big difference when you think about chess, or think about algorithms prior to the game and during the actual game of chess.
It's like 'Uh-oh, the queen is out already, let Shredder (or Deep Blue or Hydra) do the next move for me.'
That's why my bet is still on Kasparov (that is if he decides to play against a computer once again), or any of his human successor.
To wrap things up, here's an article that explains why chess grandmasters are so successful in their field.
If you read that article, you'll realize that chess and this field they call as software development are similar to each other, in ways more than all the possible chess moves combined.
Filed Under (Visual FoxPro, work.BLOG) by WildFire on 15-08-2004
Here's a simple 2:00AM code I made. Its objective is to make a certain combo box automatically reflect the tag names for the databases you are currently using.
nTagCount = tagcount()
for nCount = 1 to tagcount()
store tag(nCount) to aIndex(nCount)
.cmbIndex.rowsourcetype = 5
.cmbIndex.rowsource = 'aIndex'
.cmbIndex.value = aIndex(1)
It's too simple really but this was the first time I used this. I even had to refer to Foxpro's help file in the formulation process.
The main purpose is to create a template form for the 'File Utility' type of modules. The term 'File Utility' was something I have acquired from College MacPros (Machine Problems). This is a part of those old DOS based Programs we had back then (created in either Pascal, C/C++, Clipper 5.2) which hold the records for your database-based values, or as one of my clients call it... directories.
This has been a practice which I find useful especially when you're already in the maintenance mode of your program. Directories like this, however, should be planned in advance. The 'Design phase' of your project is a good place to start.
These directories can also be used inside combo boxes, and if in the future you would like to add values that those combo boxes display, you don't need to touch the hard code. You just either edit the database or use your File Utility module.
Very handy too when your database application is being used by more than one client.
Let's give an example.
Suppose you have a combo box for Profession. Of course you can choose the combo box builder wizard and enter the data by hand but that would be lame.
Totally lame that only castrated over-boozed programmers of the 60s do that.
You use a database approach and set the combo box to grab the values of that database.
.cmbProf.rowsource = 'DATABASENAME.FIELDNAME'
.cmbProf.rowsourcetype = 6
... where cmbProf is your Profession combo box and 6 stands for (database) fields, the source of the values the combo box will display.
You can also use the Property box to set things. Other sources include value, alias, sql statement, query (.qpr), array, files, structure, popup, DoomPortal, BermudaTriangle, RiverofLesRough and so on.
Now back to the code above (Darn I'm wandering off once again), the algorithm gets the number of tags the compound index file has, gets the tag names and stores them in an array.
Now using the values in that array, you can place the code below in an object (a 'Browse' command button perhaps).
set order to alltrim(.cmbIndex.value)
This will reflect the changes you want to view, which in my case is found in a grid that displays the sorted records.
Figure 292.1 Image too shy to enlarge itself since its design and alignment was not optimized yet. Check back later when Image.nConfidenceLevel++.
Peculiar things happen once in a while in a programming language IDE and the VisualFoxpro's IDE is not an exception.
Take this for an example:
use FILEAREA shared
index on NUMTOSTR(AREAIDNO, 5) tag CAREIDNO
index on upper(alltrim(AREA)) tag CAREAREA
Note: UDF NUMTOSTR(5, 3) returns '005'
Note: UDF is 'User Defined Function' (OK... you know that already)
So what is wrong with the above snippet?
Nothing really. In fact I'm using it on a different application and it's fine. But tonight I'm getting the 'File must be opened exclusively.' error message. So I tried transferring it from the .PRG file to the frm.Init, removed the NUMTOSTR line temporarily, executed close all commands inside the command window, closed VisualFoxpro a couple of times and the error is still there.
No other application is using the database and I'm not even connected t0 the internet. (Just in case you're entertaining that wild idea that someone in cyberspace is playing with my databases tonight)
So I thought 'FILEAREA' was an ultra-secret Foxpro reserved word and renamed the database to AREA.
Still, the problem exists.
Another reboot, fired up VisualFoxpro, executed the program and it ran sans the error message this time.
So I tried recoding the things I made, re-used the NUMTSTR function, renamed the database back to FILEAREA and placed the code back to the DatabaseInitialization.prg.
Problem's lost... I can't even recreate it.
This is one of those weird stuff I encounter once in a while. You can't even share it to someone whose skills are better than yours since it just disappeared out of nowhere. As a programmer this is quite puzzling. Programmers always have this inner desire to know the why and how of things. Why such thing exists. Why it exists that way.
When you can't recreate the problem, you can't prove that the problem isolation procedures you just did were the solution... that you used the right chant and growl frequencies.
You can't even prove that such problem exists.
Really weird. You just end up storing it somewhere behind some portal deep within your brain...
... or you end up blogging about it.
Calvin Hsia: Displaying playing cards for bridge.
Here are some VisualFoxpro articles from the Advisor Magazine:
Les Pinter points out the Differences Between Visual FoxPro and Visual Basic .NET (Two parts actually that's the first part and here's the second part).
Andrew MacNeill also writes about a new VFP9 feature that can help you lock down VFP Reports, Protect Your Reports With Microsoft Visual FoxPro 9.
I'll presume you have already read Paul Graham's Great Hackers. I posted a link to that essay days ago.
And 1,618,009 websites linked too that article as well.
Now hear Eric Sink's Great Hacker != Great Hire. It's always good to listen to two (or more) opposing sides on certain things. It helps balance the chi.
Going back to Paul Graham, the Great Hackers article has an audio version already which you can stream or download. He posted a recent article, Python Paradox, which again stirs up my interest to delve into that language.
Before I begin to scribble these thoughts that were bouncing around my mind for the past 16 hours let me tell first that I have great respect for the Open Source. From Torvalds, who my previous co-officemate system administrator worships (and I worship that SysAd during Wednesdays and Fridays), to the linux-kernel-super-computers, to the airplanes, air traffic controls and production plants that use it, the centibots, RedHat, SlashDot and lately Miguel de Icaza and Mono.
Yes... too many to mention.
Include also the top universities in this country who are pushing Java and Open Source.
In fact the area of Open Source is too broad and deep to tackle. Let me just highlight the topic partially from Dean Mikhail's post that had ignited these bouncing neurons in my mind.
Imagine a car with the hood sealed tight and the engine closed from the world -- would you trust it blindly to get you to where you want to go. -- Mikhail Online
In a perfect world, geeky car owners knowledgeable in how the internals of the car works, exist in every square block. In fact not only the car owners but every human knows how the car functions as well.
Besides, in a perfect world everyone has a Porsche Carrera GT as their 'obsolete means of land transportation' inside their 1 mile nanotech-protected garage, located in between two vehicles that have perfected the vertical takeoff.
(I won't even mention that Monica Bellucci look alike chauffeur... she's a cyborg anyway.)
Perhaps even 8 year olds know about internal combustion, the four-stroke combustion cycle, higher-octane gasoline, cooling and fuel injection systems. Add in the lubrication, exhaust, electrical and emission control systems.
These kids would even mod their cars to make it look like H-Wings from Star Wars (Too bad the mod pics are already 'off-lined').
OK... I'm exaggerating things.
But still, in reality things are not this way.
Far from it really.
Take Mr. Anderson's car for example. Let's say Mr. Anderson knows the logic behind his car that well. Inside, outside and beyond. Chances are Mr. Anderson has a wife who cares nothing about cars. Hansel and Greta, his two daughters in this world who can't even move their focus away from their cell phones when riding that vehicle, don't care either.
Now Mr. Anderson is beginning to wonder if those cell phones were attached to his daughters when they popped out to this world.
Expand that car to a bus... or to a train or a plane if you like. Sometimes humans even tend to know more about how a train works if something wrong happens like what occurred in MRT Kamuning Station this day. (I was on my way home from a certain client visit and I indirectly suffered from the jam.)
Try randomly asking passengers if they know how the engine works... chances are most of them (if not all) will give you that 'duh-look'. One out of ten would even yell or glare at you for disturbing their peace, probably 2 would give you their cutest smiles with a 'go away' subliminal mindset in the background and probably one out of one hundred would bluff their way into discussing things.
Chances are you won't even try asking for you know the outcome already.
Most of the time, these passengers don't even care. As long as they arrive safely to their destination... be with their families... just in time for a rerun of their favorite TV show.
Sans the knowledge of how the engine works or what is behind those hoods, life goes on.
And it goes on peacefully.
Replace(variations('passengers'), 'computer users')
Point is... most computer users don't give a smurf's arse on the 'internals'. Probably some of them would care knowing the logic behind things... but only few care about the source.
In fact try asking some programmers too how memory is managed, garbage collected, dangling references and the /3GB switch.
They would rather finished the tasks at hand than spend a time discussing these things to you. That is if they really know how things are done in depth.
Most users don't care how machines and mathematics merged in the form of computers with binary numbers as the battlefield. As long as they can type, edit, save and print their assigned papers and spreadsheets the world is fine.
They don't care how NudeAngelinaJolie1618.jpg was compressed, 'digitized', chopped into pieces and transform into bits once again as it passes fiber cables, lines, modems, routers and cyberspace when they're sharing those things to their peers.
As long as their friend receives the file, laughs and does things which I won't even mention here afterwards.
They just don't care.
Sad... but true.
Even in my programming-related client visits, I have experienced this countless of times already. Sometimes from 'normal users'... sometimes even from computer technicians. And I believe I'm not that boring when I talk. And I'm fresh as mint.
In fact my pet tiger and my three year old baby thinks I am interesting and cute. (OK... I am exaggerating things once again but yes the tiger exists)
Urgh. This is getting longer already... would you mind if I chop this for a while and continue this some other time?
No you won't.
You don't even care.