Login  |  Register  |  View Cart 
*
 Opinion Submissions  
  Friday, December 24, 2004
 
  News Articles 

Current Articles | Categories | Search | Syndication

Saturday, November 27, 2004
Why You Should Choose Delphi
By Nick Hodges (Nick) @ 12:45 PM :: Editorial - Nick :: 31 Comments :: 1082 Views

People are always asking “Why would I use Delphi when I can use C#? Why would I go with Borland's tool when Visual Studio and clearly closed the gap?” I think that is totally the wrong question to ask. The real question is “Why should I be using C# when I could be using Delphi?”. Here's some of the reasons why the latter is the real question to be asking:

    Delphi is easier to read. Delphi thankfully isn't a C-language descendant and so it doesn't use the ugly, horrible to read C-like syntax of say C# or Java. It uses easy to read works like 'begin' and 'end' instead of hard to read symbols like '{' and '}'. It uses a readable, sensible syntax in 'for' loops. It requires that you declare variables before you use them, ensuring that the definition and type of variables are easy to determine. It forces you to declare classes and routines in the interface section of a unit, making for much easier analysis of already written code.

    You already know Delphi – if you are currently a Delphi developer, Delphi has you covered in .Net. There isn't a single thing that can be done by other tools in .Net that you can't do in Delphi.

    Delphi has better data access. The BDP – Borland Data Provider -- provides a much cleaner and well designed interface to ADO.NET than the FCL does. The FCL doesn't provide enough abstraction over ADO.NET to even provide a single set of components to access data with ADO.NET. Access to Oracle and SQL Server require completely different sets of components and types, making providing a single-source, common front end to data impossible. The BDP, on the other hand provides that single interface, even provides components that allow you to mix data from differing databases into a single dataset. Other languages and tools don't even pretend to provide this advantage.

    Delphi is cross-platform. Delphi code can be cross-platform between .Net and Win32. Code bases can, with a bit of work, even be used in those two platforms plus Linux. Delphi is the only .Net language that provides that level of compatibility between Win32 and .Net.

    Delphi can expose .Net functionality without COM/Interop – this is an unsung feature of Delphi. Want your Win32 applications to have access to encryption? Regular expressions? Anything else in the FCL? Delphi can provide it without COM.

    Delphi can link .Net code into your EXE – Delphi provides the ability to link code into a single EXE instead of having to worry about deploying all the right assemblies in all the right places.

    Delphi handles and names events the right way. Is there anything more confusing in the .Net framework that delegates and how they are used to handle events? No, there isn't. Delphi handles this all the right way, hiding the silly, confusing way .Net does it. Instead of the confusing C# syntax, Delphi uses the model that has been proven for over ten years. Need to add an event to a component? Delphi does it clearly and simply – like it does everything.

    Delphi does IDisposable correctly. -- Only slightly less confusing than delegates is the concept of IDisposable. Do I call Dispose? Do I need to? How do I know? As long as you follow the time-test method of calling Free on any object you create that doesn't have an owner, you'll be fine in .Net. If Dispose needs to be called, Delphi will call it. If not, it won't. No more guesswork, and your code will even be compatible on the Win32 side of things.

    Delphi has been doing “Avalon” for ten years. The hot new thing over at MS is “Avalon”. Avalon is a system for storing properties and information about forms and objects in a text file separate from the silly InitializeComponents call in your code. Sound familiar? Yeah, thought so. (Side note: Partial classes crack me up. Only Microsoft could invent a “feature” solely for the purpose of making up for a gross shortcoming in their language.)

    Delphi has datamodules. Is there a bigger oversight in all of the FCL than the lack of a datamodule-like class? Sure, you can 'simulate' datamodules, but it's a poor simulation at best. Put your database controls in a datamodule, and add the datamodule's unit to your uses clause and the Object Inspector is smart enough to see the components in the datamodule when looking at another form or whatever. Datamodules let you decouple data access and other abstract concepts from the user interface of your application. In other words, datamodules rock, and other tools and don't have them.

    Delphi's third-party market is way more mature than the .Net market in general. Sure, there are tons of components out there in the .Net market. But Delphi component builders have been at this for a decade, and have the years of experience needed to build excellent components the right way. Are you going to try to tell me that Ray Konopka and the DevExpress folks don't have it all over the johnny-come-lately folks that have been building components for a year or two?

    ECO II – Delphi has a mature, existing, shipping model driven architecture that is written by people who truly understand object-oriented programming. Microsoft doesn't. They have some thoughts and ideas outlined on a web-site somewhere and promises of functionality that they don't even really understand yet. Delphi is light-years ahead in this area, and there is no reason to believe that they won't stay that way.

    Borland's ALM solutions are here now, not “in the vaporware pipeline”. Microsoft is touting Team System or whatever they are calling it. Sounds great and all, but of course Borland is selling that technology right now, not just talking about it..

And that is just scratching the surface.  You'll probably add even more reasons right here in the comments. Personally, I can't understand why anyone would ever choose C# or VB.NET over Delphi. 

How about you?

Comments
By Franco 'Gideon' Winters @ 11/29/2004 3:00 AM
As a former Delphi developer who has moved on to C#, I would like to respond to some of your remarks:
I would be interested to know what your native language is. In every natural language begin e.g. English and Russian end which I have ever come across, symbols or whitespace are used for delimitating, not keywords. Someone who finds braces "hard to read" should adjust their monitor settings, or see an optician.
Loops in Delphi are inconsistent. While loops requires a begin/end block (unless a single statement), repeat loops do not. There is no language construct which can syntactically isolate any statement to be executed after each loop, as does the C for loop; you are limited to for loops with to or downto. This is even more barbaric than Basic, which has a Step.
C# also requires that the type of a variable be declared either prior to, or upon its first reference, as do all of C's descendants. Any decent IDE will tell you the type of any symbol, and offer to take you to its declaration, without you having to manually look it up. The i,j,k: integer etc. declarations at the beginning of most pieces of Delphi code so that for loops (or your while/repeat workaround) have a variable to loop with are a pain to type, clutter the declarations section and are of absolutely no value to anyone (Wirth realised this himself and the for loop implicitly declares its own variable in his subsequent languages. Unfortunately, he did not work for Borland).
The interface section merely duplicates the code explorer of modern IDEs, but without the much nicer icon and font hinting tree interface which can be explored in parallel to the code in the editor. It does, however, mean that the developer must tediously synchronise two copies of each declaration in different parts of the file (the IDE tries, but often requires manual intervention for this pointless task). It does not even achieve the original Pascal intention of documenting the "public interface" of a unit, since the private members of exposed classes must also be declared in the interface.
Learning C# required very little effort for me; in fact, anyone who has the vaguest familiarity with any C-descendant language will pick it up while learning .NET just by following the C# examples.

By Nick 'Nick' Hodges @ 11/29/2004 7:28 AM
My native language is English.

I don't need to adjust my monitor or get glasses: It's clear that "begin...end" is easier to read than "{...}" They are also easier to line up vertically. Can't see much debate on that one, really.

Loops in Delphi (there are three of them -- powerful feature) are three separately defined statements. They are inconsistent, I suppose, but they all work in different, unique ways, so I suppose they /should/ be "inconsisten".

Variable declarations at the beginning of a routine are valuable to everyone. One need not hunt through code looking for the declaration of a variable. All variables are defined in a known, easily found place.

The interface section gives an uncluttered, clear look at the definition of a class, without having to do any codefolding, reorganizing or anything at all.

I note, too, that almost all of your comments rely on the IDE to make the code more readable. What if the code you want to read is in a book?

I'm sure that learning C# is easy for those familiar with C. Doesn't effect anything above, of course.

By Steven 'Babnik' Camilleri @ 11/29/2004 7:51 AM
When it comes to readability, the single thing that makes Pascal code so much easier to read than C/C#/Java code is the Interface section. At a glance, you can see what a class does without the need for comments. The code comments itself. Why do you think Visual Studio allows you to collapse sections of the code? What do you get when you collapse the code? Yes, an interface declaration! Notice how redundant this feature is in Delphi 8. (not sure if it's in Delphi 2005!)

As to C# being easy to learn. It sure is, especially to us Delphi developers! Testament to how good Delphi is. (and has been for a while now!)

By Roland 'Roland' Beenhakker @ 11/29/2004 10:24 AM
I also find the interface section of Delphi very usefull. In VB and C# it is always a puzzle to find out what a class does. (or should be doing). It is a usefull roadmap, and with the new refactoring thing even better to use.

--Delphi has been doing “Avalon” for ten years.
Like this one the most, never thought about it in that way!


By Craig 'craigvn' van Nieuwkerk @ 11/29/2004 1:31 PM
"There isn't a single thing that can be done by other tools in .Net that you can't do in Delphi."

What about compact framework development?

By Nick 'Nick' Hodges @ 11/29/2004 2:02 PM
Craig --

You got me there. You can't do CF in Delphi....yet.

Nick

By Steve 'steve' Teixeira @ 11/29/2004 2:39 PM
I am, of course, a huge supporter of both Delphi and Borland. However, I tend to use C# for most of my work these days for a variety of reasons, which maybe I'll discuss in a future editorial.

Regarding Nick's editorial, it seems that a lot of what is discussed is syntax preference. As another poster points out, "begin" and "end" are not so friendly if you're not a native english speaker. And I know many people that prefer the curly braces. Personally, it's a matter of mood for me; some days I prefer begin/end, some days I like the braces.

I do like Delphi's don't-worry-if-it-supports-IDisposable mentality (especially for Win32 compatibility), although that approach does tend to clutter the code with lots of try/finallys. In straight .NET coding, I tend to call Dispose() only when needed, and for this I must say that C#'s "using" statement is a really nice alternative to all of the try/finallys, as in:

using (temp1 = new obj, temp2 = new obj)
{
// use temp1 and temp2
.
.
.
} // Dispose() automatically gets called on temp1 and temp2


Anyway, whatever... it's just language syntax, and you can't necessarily convince someone which is best for them. Language preference is a personal thing.

Aside from the language stuff, which - again - isn't arguable in IMO, I do feel compelled to make a comment on one of Nick's claims:

>>There isn't a single thing that can be done by other tools in .Net that you can't do in Delphi.<<

Aside from the obvious -- .NET CF, which Craig mentions, this definitely wasn't the case in my experience with Delphi 8. When writing chapters for "Delphi for .NET Developer's Guide," I found a number of things I couldn't do in Delphi that I could do in C#, particularly in the area of component development. Most of these limitations had to do with a handful of bugs or limitations in the attribute support of the Delphi 8 compiler.

While I did manage to work around almost everything, the problems I encountered caused the project to take much longer than anticipated. I can accept this kind of thing in my own projects, but such a delay would have been killer had this been a project I was doing for a client.

I haven't had a chance to try all of these things again in Delphi 2005, but I'm hoping the capability gap has closed or at least greatly narrowed.

By Nick 'Nick' Hodges @ 11/29/2004 4:52 PM
Steve --

I didn't actually make any mention of "preferences", but I suppose that's implicit to a certain degree. However, I think that any expert on linguistics or whatever is the academic discipline is that studies such things would agree that begin...end pairs are easier to match up than {...} pairs, especially at a glance. This seems axiomatic to me. In addition

for i := 0 to 10 do

seems, oh, 132 times more readable than, than.... well, whatever that mess of plus signs and whatever the else it is that C++/C# does.

That's not to say that some don't /prefer/ one over the other, but that one is easier to read -- hence my point.

As to the Dispose issue:

The notion that "cluttering up code with lots of try/finallys" is a bad thing is so ridiculous, I won't even address that.

You say "In straight .NET coding, I tend to call Dispose() only when needed." Well,that's sort of the point. When is it needed? How can you tell?

Using is cool, I admit, but of course it's just a glorified try..finally. And why should we clutter up our code with lots of usings? ;-)

I agree, language preference is a personal thing. I'm not arguing preferences, I'm arguing which language is better. One might "prefer" COBOL syntax, but I don't think any serious consultant would recommend it for your next .Net project.

As for CF development -- you guys are right.

As for limitations in component development, I'd like to hear them. BTW, you can very easily override a property (one you've mentioned before). If there are attribute problems with Delphi, those are bugs and not problems with the language, per se. I assume you've reported them in Quality Central. ;-)

Nick

By Matt 'mabster' Hamilton @ 11/30/2004 12:53 AM
How about TActionList? In my reading I'm yet to find anything in the FCL that will centrally manage common actions, automatically updating captions, images, enabled/disabled state etc on all the UI elements that call them.

By Nick 'Nick' Hodges @ 11/30/2004 7:43 AM
Matt --

For action lists on the FCL side, you need to get


CommandMaster! -- http://www.componentscience.net/Elements/CommandMaster/


Now back to our regularly scheduled heckling and debating. ;-)

Nick

By Dallas 'dallasg' G @ 11/30/2004 7:58 AM
I just downloaded the trial, and converted an app from d7, very impressed with D2005.
As for the speed issues i can live with them for now, lets see what the patch does.

As for CF development, how many people are really doing development for this? I personally dont think its mainstream yet as there are many non-MS software houses out there.

As for limitations in component development, I'd like to hear them too!

By Dallas 'dallasg' G @ 11/30/2004 8:02 AM
I just downloaded the trial, and converted an app from d7, very impressed with D2005.
As for the speed issues i can live with them for now, lets see what the patch does.

As for CF development, how many people are really doing development for this? I personally dont think its mainstream yet as there are many non-MS software houses out there.

As for limitations in component development, I'd like to hear them too!

By Steve 'steve' Teixeira @ 11/30/2004 9:23 AM
>>As for limitations in component development, I'd like to hear them. <<

I did talk to you about them in person, Mr. Short Term Memory. :) However, I'd like to try the stuff in 2005 first before making any public noise about it.

>>If there are attribute problems with Delphi, those are bugs and not problems with the language, per se.<<

True, but on the other hand: if it doesn't work, it doesn't work. If a tool is not productive for a certain type of work, it doesn't really matter from the standpoint of the user whether it's because of bugs, bad design, lack of features, etc.

>>I assume you've reported them in Quality Central. ;-)<<

CodeWhat?? :) No, but I did have several conversations with Danny about them.

-steve

By Steve 'steve' Teixeira @ 11/30/2004 9:24 AM
>>CommandMaster! -- http://www.componentscience.net/Elements/CommandMaster/<<

CommandMaster is great! And here's a secret bit of CodeFez inside scoop: CommandMaster was written primarily by our own Julian Bucknall.

-steve

By Nick 'Nick' Hodges @ 11/30/2004 10:12 AM
Steve --

You are right: If it doesn't work, it doesn't work. I shouldn't have implied otherwise.

However, I'll argue that your problems, while needing to be fixed, are corner cases purely for the component developer. (Just trying to recover a little face here...)

I'll look forward to hearing what can be done in C# and can't be done in Delphi. ;-)

Nick

By Steve 'steve' Teixeira @ 11/30/2004 11:09 AM
>>You say "In straight .NET coding, I tend to call Dispose() only when needed." Well,that's sort of the point. When is it needed? How can you tell? <<

I don't know about other folks, but I simply type ".D" after the object in question to see if it supports a Dispose() method. Pretty quick and easy, and less work for me than an unnecessary try/finally block.

-steve

By marc 'mh' hoffman @ 11/30/2004 12:03 PM
"Delphi handles and names events the right way."

Because calling them "property" rather then "event" as C# does is just so much clearer?

By Virgil 'hardcoded' Dupras @ 12/1/2004 4:41 AM
with Anders Hejlsberg at Microsoft, C# can only go upwards and Delphi can only go downwards. That is what bugs me the most about Delphi. I like it a LOT, but the future doesn't look very bright for Delphi enthusiasts.

The more I look at Python, the more it looks like a very good way to go... Now THIS is a graceful language.

By Dallas 'dallasg' G @ 12/1/2004 7:28 AM
I cant see delphi going down becoz Anders has left, yes he was the creator, but the spirit of delphi lives on!!!

And I have faith in Danny, and i hope he makes it better than anyone could!!

By Franco 'Gideon' Winters @ 12/1/2004 7:55 AM
Reply to Nick's response:

I'm not sure why it is "clear" that begin .. end is easier to read than { ... }. I can accept that it might be different for different people, but having been brought up reading/writing a natural language, my brain interprets { ... } much more easily than begin ... end.

As far as loops are concerned, why do For and While end with a Do, while Repeat is a block terminated with Until? A purposeless inconsistency, although it probably only bothers consistency fanatics (such as myself).

As for the var section; I don't like scrolling up and down to declare variables or find their declarations. In C#, I can declare variables where I first use them, without breaking to scroll up, declare, then scroll back down to where I was working. I can look up a variables declaration in the code explorer without scrolling up from where I'm working (as you can in Delphi), making the var section an unnecessary annoyance whilst writing. It was put into Pascal because in the 1970s every byte counted, and it was worth forcing developers to keep all memory usage in a "catalogue" to ensure that none was wasted.

Again, the interface section duplicates the code explorer while forcing the developer to quasi-manually keep two copies of each declaration synchronised. I agree that Pascal is easier to work with in notepad, but these "features" are just obsolete annoyances with a modern IDE.

Incidentally, I've never coded in C (or C++); I picked up enough by reading documentation and books on general software development, where C is usually used for examples. This, with Delphi experience, should be sufficient to make C# easy to pick up. Most of the work is in learning .NET.

By Dallas 'dallasg' G @ 12/1/2004 9:08 AM
Steve: I would like to know some of your reasons for using c# over Delphi, having bought your books and used them to teach myself and others I would find this very interesting

By Steve 'steve' Teixeira @ 12/1/2004 1:02 PM
I'm pretty amazed by staying power of the whole "Delphi will suck because Anders left Borland" shtick. Sometimes I wonder if people realize that Anders left Borland EIGHT YEARS AGO in 1996. He left in the middle of the Delphi 3 development cycle, and SEVEN major releases of Delphi have shipped since then.

Look, there's no doubt that Anders' departure was bad for Borland and good for Microsoft. And there's no doubt that Delphi lost some of the innovative spark when Anders left -- that's no knock on the team, just a plain fact of life of losing a man of Anders' exceptionally rare talents. However, that is all ancient history. It's not like every release after Delphi 2 sucked, people. How about judging the products on their relative merits in THIS century?

Even Boston Red Sox fans have finally let go of Babe Ruth, Bucky Dent, and Bill Buckner. Let's please agree to lay to rest The Curse of the Hejlsberg.

By Steve 'steve' Teixeira @ 12/1/2004 1:03 PM
Dallas: You got it. I'll have to gather my thoughts on C# and Delphi, and I'll post it as an editorial. P.S. Thanks for buying the books! :)

By Nick 'Nick' Hodges @ 12/1/2004 2:17 PM
Steve --

If I want a try...finally block, I just type 'tryf" and hit CTRL-J, and I have what I need.

Nick

By Nick 'Nick' Hodges @ 12/1/2004 2:26 PM
Franco --

You write: "I'm not sure why it is "clear" that begin .. end is easier to read than { ... }. I can accept that it might be different for different people, but having been brought up reading/writing a natural language, my brain interprets { ... } much more easily than begin ... end."

Consider this: Which is easier to read:

procedure Something;
start
if this then
start
DoWhatever;
finish;
finish;

or

procedure Something;
$%
if this then
$%
DoWhatever;
%$;
%$;

Seems obvious that the first is easier to read and recognize than the latter.

APL is not a popular language for a reason. Some my /prefer/ it, sure, but that doesn't mean it is as objectively easy to write as pascal. There are objective measures that one can apply to ease of reading. Try reading binary code. Some may /prefer/ it, but only a fool would argue that binary code is just as easy to read as Pascal.

You write: "As far as loops are concerned, why do For and While end with a Do, while Repeat is a block terminated with Until? A purposeless inconsistency, although it probably only bothers consistency fanatics (such as myself)."

I guess I don't see any inconstency. They end differently because they are different statements.

As for the var section -- First, "ease of typing" is not a reason to choose one construct over another. Ease of typing is nice, but ease of reading is nicer. The advantage of the var section is that the declarations are clear and easy to find. When looking at C# code, I have to constantly hunt for the type of a variable in the middle of the code, and it could be declared anywhere. It's made harder because the type is declared first, and then the variable name, embedding the name deep in the code itself and not on the endpoints of the code.

I submit that declaring an interface for a class makes class design easier and better. Seeing the class interface easily and in one place (this is hard in C# even with code folding) is a big advantage to good design and good coding. Again, saving keystrokes isn't a reason to discount constructs.

Nick




By Dallas 'dallasg' G @ 12/2/2004 5:49 AM
Thanks Steve.

Yes Anders was good, but i quote from my previous post... I have faith in Danny and after reading his blog and working with Delphi 4,5,6,7 Things can only get better...
As for D2005 WOW

By Allen 'abauer' Bauer @ 12/2/2004 9:23 AM
Not to knock Danny at all here, as he is a very exceptionally talented guy. I've been honored and priviledged to have been working with him for nearly 13 years. Anders and Chuck were also excellent to work with. Chuck was my mentor for many years. I owe a lot to his guidance and expertice. However, I should point out, and Danny would also vehemently agree, that Delphi was never and will never be produced by a single person. There are *many* talented and exceptional developers on the team. Many of whom you may never hear about. To hang your aspirations and hopes on a single individual is setting yourself up for disappointment. While these few people are certainly more visible than the other members of the team, they are only one part. A healthy team is always growing its more junior developers into more prominent leadership roles.

By Dallas 'dallasg' G @ 12/3/2004 12:52 AM
I agree 100%, so if i can get all there information I would would put a delphi hall of fame on my website...

Truely there is no better Langauge than Delphi

By Mario 'mamcx' Montoya @ 12/3/2004 1:29 PM
Exist a kind of advantage that Delphi have and not VS:nET/VS... and is about cost...all about cost.

The MS tools encourage deep dependences, causing problems, errors and more cost in deployment. Is not only carry a runtime like in VB 6 or .NET, is a lot more. For example, you can need this version of the MSXML parser...that cause, have this version of IE... but installing IE is not installing a component or a aplication (like with Mozilla Firefox) is more a OS upgrade. And sometimes, that cause a SP to be installed. That happening to us, because we write 200 lines of code, for a program running in a Floppy made with FoxPro. And in the end, was a failure. However, we simply relearn to do Fox with Fox things and replace the XML parsing with a DBF and whoila, we only carry the size of 200 lines of code and zero failure and dependence.

Obvious, you can say "Was a failure use XML, why not DBF from the start?" and that is the problem, MS tools ENCOURAGE big dependences.. in conferences, in MSDN, in the tool himself. And when the development progress, sometimes can feel more easy disturb the customers than change to a better solution. Good for us that was in VFP, and in some sense like with Delphi, VFP permit do a whole application with VFP and only VFP. That is a strong point with Delphi too.

I work in VS.NEt, exactly, with ASP.NET. And is great. And is impossible do a total .NET solution: We MUST buy thirdy-party for have basic things... With Delphi is possible do a end-to-end solution and thirdy-party is only because is for a cool look, or because is more easy, but no because a development is impair so much.

Delphi cause exposure to others tools. Is not only have a good thirdy-party only. Is with Delphi that people note things like FireBird or ... is increible how easily can some applications be made with a embebed database. However, in MS camp, you only knwo about Sql and Acces, and Oracle only because some big customers use it... And that traduce in lower deployment cost.

Is not necesary switch tools so much. I remeber in a aplication for schools how i use Delphi for do utilities and applications than backup data, configure things and help in "hide" the imposibilities of the MS tools. I still have a application that fit in a Floppy and have a grid, full editing and reporting (graphical) with Delphi 7, Rave, ADO (the MS produce XML recordset so i must use that). That was in the top 3 selling points of that application and i do that in 3 days... including investigating how reduce the exe output for the xml fit to inside the SAME floppy. That kind of flexibility amaze me... like when i decide to do a FTP client, or a page producer or anything I KNOW i can have a solution code by myself or in the next Google search, at lower cost than other programing languages.

And the quality of thirdy-party, man, the quality! Is part of my job review and recomend .NET thirdy-party tools for one company... I prove several of +$1000 toolsets and is very disapointing... But i know that have RemObjects, DevExpress, TMS Software and much more, plus very good open source, that simply work and work well.

Is very shocking how easily i can produce any kind of solution that cost more money, more time and more programers for others. Is more shocking when i show in yours face of my old managers; and still prefer do the 8 month development.

Also, a side effect is that when some guy know that, and not can use the best tool, start strongly the idea of fund a company, because the life is so short for spend so much money & time in others tools, and disturb customers with unnecesary overhead and cost... So i did that! I fund www.solucionesvulcano.com is not big and i know, not can made me rich. I can code ASP.NEt solutions for eat today and i'm preparing a application where Delphi is key for the succes (because deployment). So, i good side effect is that Delphi produce Enterprise, while MS Tools produce happy slave workers ;))


By Dallas 'dallasg' G @ 12/9/2004 6:25 AM
hows the thought gathering going Steve?

PS. are there any more books coming? C# or Delphi

Post a Comment
You must be logged in to post a comment. You can login here.
 Copyright 2004 Codefez Inc. CodeFez Inc.  |  Terms Of Use  |  Privacy Statement