Great Site

I just found this site, The Daily WTF. Your average computer user won't find much use in it, but programmers love it! They post pieces of code like this:

if (errMsg.indexOf("Violation of UNIQUE KEY constraint 'UQ__mbrs_pwd'") != -1)
return "The password entered is already in use. Please enter another.";


And there's always some terrible thing wrong with it. The post with that code is called "Uniquely Secure".

I notice users on there that have trouble grasping what's wrong with the code sometimes, and it's good that they visit this site every day or whatever, since it's not only funny, it's a brain teaser every day.

Here's another quick sample:

function executeQuery($string)
{
GetDatabaseConnection();
$result = mysql_query($sqlText) or die(
"Query failed " . writeErrorToLog(
$_SESSION['USERNAME'],
"Query Failed: " .$sqlText . " " . mysql_error()
,$scriptName
));
return $result;
}


function writeErrorToLog($owner,$description,$script)
{
$script = str_replace($_SERVER['DOCUMENT_ROOT'], "", $script);
$sqlText =
"INSERT INTO errorLog (ownerID,time,description,script) " .
"VALUES ('" . $owner . ",Now(),'" . $description . "','" . $script . "')";
executeQuery($sqlText, $_SERVER['PHP_SELF']);

return "";
}


At first glance (I think it's PHP) it doesn't seem like much is wrong, other then they do the cardinal sin of writing to the database to report an error when there's a database error! But anyway, you will notice that if a piece of code fails to write to the database, it will always infinite loop! The reason for this is that, for one, there could be a database connection problem, and it would never succeed, but more interestingly, there seems to be a missing apostrophe (') in one of the values in the sql statement when writing an error! So no matter what, if it fails once, it's doomed for infinite loopage.

And the site has one of these per day, and I love reading stuff like this. I recently bought a book called Java Puzzlers: Traps, Pitfalls and Corner Cases. They're fun brain teasers, and most of the time, in the Java one, you can't tell what's wrong (having 10 years programming under my belt, that's odd!) and then you go read the solution and it's like some bit can't be set when calling a certain function. Java's a pesky language :) I still love it though.

Moving On

I'm extremely disappointed to inform everyone that stringed.org has been treated to a significant upgrade... a security system. Well, I simply use the same security system as I had for this site, made no modifications to the inner code (since it's perfect), and now I have a per item per operation security system in place for stringed.org.

That "per item per operation" bit might be confusing. Basically, say I want to allow someone to edit News but not be able to delete it. Or to have full permission for News, Photo Albums and Polls but not for Downloads. I can do all that and I didn't have to change the old security system that I built. Why? Well, I would start out by saying I've seen quite a few hand built security systems in my 4-5 years in the professional business of software development to know what works and what doesn't. Or to pick the pieces that work from other security systems that might not be that great overall. As Picasso says, "Good artists copy, Great artists steal."

So what else is new with it, you ask with desperate anxiety... Hmm. I have listeners in there for when objects are saved and deleted. This is more for editing the security system, since it's kept, for quick lookup, in the application map. If I don't reload the registry after making a change, that change never takes place, as far as the security system is concerned. Also, it will be an important piece behind "Attachments". Although, I might just write a new engine for that.

Also, since you're dying to know, there was a bug on the form when I had two dual-select lists. Fortunately, this bug never made it off of my computer, as my wicked javascripting skills extinguished it when I found it. I have two dual-select lists on a "SecurityGroup" object, since Groups have a list of Privileges and also a list of Users. I've said too much :p

I had debated trying to create a new security system. This would be so I wouldn't have to create a new menu system, as the menu system relies heavily on the current security system. So, since I didn't want to write a new menu system, and a new security system, I was forced to think brilliantly into the current solution that doesn't change anything and does not restrict anything either. The menu will work, the forms will work, and the rest of the site will work just as it's supposed to, as you can see by going to this page. You will see "You are unauthorized to see this page." or something.

One other helpful change is for the lists that list an object that might have the same name as another object in the list, but have a foreign key "parent" that will be different. On the old version of the site, if you go to add a library, it lists books with just their title. But, you can't tell who wrote those books without first going to the book list and seeing. Now, they are listed with their "parent", in a book's case, Author. So, my book shows up as "Jason Connell - Orientation of Objects". You can see this illustrated here, along with the two dual select lists on Group. Basically imagine the list being "view add delete edit view add delete edit view add delete edit". That's why I added that :) But also, you can see it in my User list... A User for stringed.org has a foreign key to Author, making Author it's "parent", so now, the User will display "Author Name - Username".

It's pretty sweet. I am trying to think of other stuff that I did for it. I didn't have that much time this weekend with my neice Megan's Christening, hanging out with Kira, Caden, Ethan and Danny, and my brothers, watching lots of college basketball, etc. This week should be a big time of productivity, since I can finally start on Attachments!! They'll be neat.

It's a beautiful thing

I took out the "Book" form for now, otherwise it would be a gigantic cluster@#%@@#, and I limit the file size to 1000 bytes (less than 1KB). Other pictures here and here.

And with that, stringed.org's underlying software is ready for some major overhauls!! There's this whole huge thing I want to do to it yet.

Progress rocks the mother f@#%@#ing house

Check out stringed.org NOW!! Updates include:

Customizeable actions - specify what a user can do with an object (add, edit, delete, view). You can see this in the book list, it shows a "view" link. If I don't specify "edit" for an object, the whole site has been updated to account for this, so you won't be able to trick the site into being able to edit something that isn't editable (or edible :-p )... or deleteable for that matter.

Lists are perfect - As well as the below mentioned "many to many problem" (which you can see at work on the "Library" form), all lists that are sequenceable can be sorted (See Chapters on a book and Books in a library). You can add a list to an object that hasn't been saved yet. (This was more of an "uncomfortable with the greatness of 'dumb'" situation, as I just had a line of code that said "if the object hasn't yet been stored into the database, don't process lists". You would have seen those repercussions yesterday if you logged on, but not anymore). Obviously, also, the subforms work perfectly.

Bitmasked int field - This can be seen at work on the "Library" form also. Right now it takes parameters for the values, but I will write plugins for it that it gets it from the database and shows them as checkboxes like they are now. There's also a corresponding output component for bitmasked integers.

Still a lot to do... I have to have it so you can specify something's a file field, and make a cool control for that, and there's probably other types of fields that I haven't accounted for yet.

Also, I registered the domain name that Salzburg will be found at later, but I can't tell you it. Secrets rock even more than progress.

Of Course!!

Some things you are so used to thinking about one way, that to think about it another way IS considered to be "thinking outside the box". Even if you were thinking about it wrongly before, and now are thinking about it correctly.

This happened to me sorta. It was more of a case of not making the obvious conclusion about something. All the facts were presented, sugar coated, with arrows pointing to a conclusion, but I only came to it through trial and error last night.

Databases are merely containers for data, and we have to use the tools that they provide (foreign keys, primary keys, indexes, unique constraints, SQL statements, etc) to really find out the meaning of the universe. Well, I didn't get to that point yet, but it was something close. The dreaded "many to many relationship" problem. I'll explain.

The simplest way to put it is that a many to many relationship is when one single object (we'll call it Object A) has many of some other object (Object B), but one of Object B can "be in" many of Object A. The best real world example I can give, using my "Library" model on stringed.org, is Book (Object A) and Word (Object B). A book will have many words in it, and a single word can "be in" many books (and in the case of Words, it can be in a book many times).

The simplest way to portray this in a database is having a Book table and a Word table, and then you have a "link" table (probably called BookWord) that has foreign keys to both a Book and a Word.

The way "dumb" was originally created, I had no functionality to handle "many to many" relationships. I had thrown in some XML to be able to handle it in the future, but never did anything with it. (Originally, I'd get lists of the "link table" object, with the references loaded, and then populate the list that was part of "Object A" with the list populated full of "Object B" objects, all manually, everytime I needed it. My News object has many categories, and a category has many News, so I'd get a list of the link table "NewsCategoryNews", and then grab the "Category" part of that object, and my News object actually had a list of "NewsCategoryNews" objects, instead of simply a list of "Categories", which it should).

Then last night, as I was creating a control and adding functionality to potentially handle "many to many" relationships, it dawned on me. With previously created tools in "dumb" (namely a MappedListProperty which says a certain object has a list of objects, as an Author can have many books [a one to many relationship unless you include functionality to have many authors write a book, which the model doesn't include]), the conclusion was obvious. A book has a list of Words!! I know, it doesn't seem brilliant, but now it all works. See, even if they are many to many, a book still just has a list of words, and a word has a list of books that it is in. All I had to do was simply add functionality to handle this, which basically meant to add some attributes to a MappedListProperty XML node, and override some functionality used when saving and loading a ListProperty. It was easy.

Now, a News object can have a list of "Categories", instead of a list of "NewsCategoryNews" (the link object). "NewsCategoryNews", the table and the object, still have to exist, however, because "dumb" still uses it to populate the "Categories" list for a News object.

I don't have that latest uploaded yet, but I will tonight. It works beautifully. Right now I have the model set as "Books can have many Genres" (a genre is like "Suspense", "Horror", etc), and "A Genre can have many books". All I do is specify, in books, and actually in the "Genres" list property, is that a book can have many Genres, but also a Genre can "be in" many books. I specify the "link table" to use for the many to many relationship, and it's smooth sailing after that.

So to review: Many to many relationships cannot be handled with just 2 tables. You need 3. The two tables to be linked, and the link table. So to represent it in software, you just need to specify that there's a link table, and handle it accordingly. Side effect: Never write unnecessary code again :)

Updated huge investment in time again

stringed.org has been updated again. What's up there is the result of my latest efforts, where I started it over, wrote some new controls for it, fell asleep and drueled all over it, etc. The "Remove" functionality doesn't work, I've yet to find the best way to do it. There are some kludges in the software, but none that were avoidable. So that sucks. I can offer a huge explanation about that but I have other things to attend to.

As you can tell from the site, there are a few very confusing things going on. First off, this might be the most confusing form ever. But that's ok. It'll really be used mostly for this sort of thing. And it won't be too confusing with only one child form (just a book form for author) as opposed to any number (books have chapters, so that's a form, and there could be an infinite amount of inputs on the screen... this won't ever happen for me).

It's not done though. I still have a few things planned for it, but it's really close. I can't see the rest of the site taking much more than a few weeks. I have to get to work on my "Salzburg" game so I'm the first to market. Not that I'm making money on it, but it just shows originality to employers if you're the first to market an original and creative idea. Then I can get jobs anywhere :)

Word.

Happy Valentine's Day!

Woohoo.

In other news, I have the latest version of stringed.org up there. Actually, the official name of the software is "dumb web" since it's written on top of "dumb". At home I'm testing with the following data architecture: Authors have books, books have chapters. So when you add or edit an author, you'll be able to add books for that author and add chapters for each book, while on the author form. It is 100% dynamic. It's working except for some quirky validation issues, however, what's on the site works 100% (with just books and authors). As soon as I get subforms inside subforms inside subforms working, I'll post that version up :) Please note that I recreate the database each time, so your additions / changes will only remain intact until the next update.

I still have a lot of work to do, but I should be pretty close by the end of this weekend.

I played "The Movies" but only for a few hours, and didn't get a chance to take any screens. There's no easy way to do it. But here are screens at GameSpot. It's a fun game, but more like "The Sims" with it's "Keep your stars happy" theme. But, there are a lot of neat things going on... writing your own scripts to movies, directing movies, post production of movies, buying sets, researching technology, etc. I recommend it if you find that kind of stuff interesting.

Kodie was out in the snow the other day, and what happens when a furry little dog runs around in 16-22 inches of snow for an hour?! I'll post that picture tonight :) It's HILARIOUS. And Cute.


That's what happens to furry little dogs in the snow :)

Today I was tired, so I went to Dunkin Donuts and got a medium for the ride into work, and an extra large for at work!! To make it look like I was ordering for 2 people, I got a few donuts. I should just shamelessly admit that I can drink like a gallon of coffee without it having any effect on me, that way I don't have to get donuts to go along with them. I could do without them :)

stringed.org launches!

It's very, very young. Basically, last night, I went from being able to only add a new "Author" to being able to edit and delete them, as well as detect that a book has an "Author", and when editing a book, to show a list of authors to choose who wrote that book. Feel free to try it out. There will be bugs for a long, long time, and I've noticed quite a few on those two simple objects, so just bare with me.

There are quite a few object types that I need to support in order to be able to convert this website over to the new system. First thing's first, though. Naming the software! Considering the fact that it's using the same exact version of "dumb" as this website, and the whole front end is built using information collected from "dumb", it's only right that it be called "dumb web" (read about it here).

So far, the development is progressing nicely. I hit a few speed bumps last night, but just glided over them and now it's just a matter of supporting more object types. Right now, you can see that "Foreign Keys" are supported (if you know your database talk), as well as strings (like Author name and Book title), and another type of string that I'll just call a "long string" (or "text" to the db folk), which is tested with a biography on the Author object. Other object types to support would be dates, files, many to many lists (like news can be in many categories), one to many lists (a poll's answers are entered in a list), and a potentially long list of others. It should be fun, and will probably never be done.

Check out the site here. I prefer that everyone access it without the "www." in front, because it just looks cooler, but the non-cool way is still supported... for now :-P

More Math

This is basically a personal post to Todd, but anyone is allowed to join in. Feel privileged. Or you can use this time to listen to my latest song, "Should Be Sleeping", at the bottom of this page.

I did some research on amicable numbers, and tried and succeeded to write a program that calculates an amicable number given a number. Then I tried to write it so it loops for a while, listing any amicables it finds. The problem is it's slower than death. The key, obviously, is finding the right function to calculate a sum of divisors of a number. It's brutal. This is what I have so far.

    private int sumOfDivisors(int n){
        int sum = 1;
        int max = (n/2)-1;
        for (int i = 2; i < max; i++){
                int x = (n/i);
            if (n % i == 0 && i < x){
                sum += i + x;
                max = x-1;
            }
        }
        return sum;
    }


I adjust "max" based on the last divisor, so, knowing that (for instance) 3 divides into the number 81 times, it should now only loop up to 80. Then, later on if it finds that 9 divides into it 27 times, then it will only loop up to 26. This is just knowing that basically, since we're counting up, there will be no number above 27 that divides into the number that hasn't already been accounted for. Try it out. Then, to take care of that number, I add it to the sum and just adjust the max loop amount, significantly dropping the iterations needed to get the sum of the divisors, improving overall performance by a factor of around .00000001 :) Here are some results.

(NOTE: It takes 50 seconds because I'm looping from 10,000 to 11,000, checking each number for an amicable twin. To find out if a single number has an amicable twin isn't *that* bad :p )

10744 has an amicable number of 10856
from 10000 to 11000 took 50178 milliseconds.


Then from running it without adjusting the max loop

10744 has an amicable number of 10856
from 10000 to 11000 took 50228 milliseconds.


So, that's the key. If there's a formula out there for getting the sum of the divisors, it would greatly help, but I searched for a while and couldn't find it.

The general function body looks like this

        int amicable = 0;
        int sum = sumOfDivisors(n);
        amicable = sumOfDivisors(sum);
        if (n == amicable) {
            // We have an amicable number stored in "sum" (not "amicable", since it will be the same as "n" if they are amicable)
       }


50 seconds sucks. There should be something better out there. I even tried to save the trouble of searching numbers later on in the sequence that have already been determined to have or not have an "amicable twin". Anywho. It was fun.

[Update] I just remembered that division on a computer is like painting. It doesn't like to do it at all, but is asked to do it because the person who usually has to do it doesn't feel like it either, but the person asked is pretty good at it. Anyway, I changed the function so that it's faster. It doesn't divide as much. I just ran it on my laptop (1.5 GHz, 1GB ram, Linux), and it did the loop (10,000 - 11,000) in 125 milliseconds. I'd say that's a bit improved... unless it's just Linux :)

Found amicable (28,28)
28 is also a perfect number
Found amicable (220,284)
Found amicable (284,220)
Found amicable (496,496)
496 is also a perfect number
Found amicable (1184,1210)
Found amicable (1210,1184)
Found amicable (2620,2924)
Found amicable (2924,2620)
Found amicable (5020,5564)
Found amicable (5564,5020)
Found amicable (6232,6368)
Found amicable (6368,6232)
Found amicable (8128,8128)
8128 is also a perfect number
Found amicable (10744,10856)
Found amicable (10856,10744)
Found amicable (12285,14595)
Found amicable (14595,12285)
Found amicable (17296,18416)
Found amicable (18416,17296)
time took was 3266 milliseconds


(NOTE again... Description of Perfect Numbers)

That can't be Linux. 3.2 seconds?!? That's a loop from 2 to 25,000!! The other function took 50+ seconds to go from 10,000 - 11,000. The machine at work is a 1.7 GHz (faster than this laptop) with a GB RAM running Windows XP SP2 and the same version of Java. 4 divisions cut to 2 doesn't normally shave off 50 seconds... now I'm curious.

[Update] Forget it. I forgot I was throwing in a sleep everytime it looped... idiot. Anyway, Windows is still slower on a faster machine. 171 ms for 10k - 11k, vs 125 on Linux.

I wish my SSN was 123-45-6789

Because I'd be famous to programmers everywhere! SSN of course is Social Security Number. Whenever we programmers write a program that takes an SSN for input, the most highly used test data for the field would have to be "123-45-6789". Just because the counting style of the number lets you know when to stop. "Stop at 9", I always say to myself. Whereas if you were to put in "111-11-11111", you might enter too many numbers (as I just did, which, of course, is a good test of your software).

Similarly if you live at "123 Main Street, Anytown USA". Your address, probably only second to Santa Clause's, is one of the most written in the world :) Of course, this is all speculation.

But out of those two examples, there has to be someone with the SSN of "123-45-6789". There'd have to be! Well, no there wouldn't. That sequence of numbers allows for 1 Billion permutations (10^9), and there's *only* ~280 Million in the SSN using world. I hope in my next life I get that SSN.

Fun with Math

Yesterday, I wrote a function for Todd to show him some Java since he's learning it. It was a Fibonacci sequence calculator. Basically, you pass in the index of the sequence that you want, and it'll calculate it for you. So, today, I'm killing some time, and I wanted to figure out how much time it took to figure out some high up numbers of the sequence. Well, the function that I wrote originally pretty much sucks, but it works and it conveys some pretty fun stuff in computer science. First, an explanation.

The Nth number in the Fibonacci sequence is defined as the (N-1)th number plus the (N-2)th number. Or, the Sum of the previous two fibonacci numbers in the sequence. The sequence starts as 1,1,2,3,5,8,13,21,34, ... ending with F(N-1)+F(N-2), or F(Infinity-1)+F(Infinity-2). So it doesn't end. Anyway, there's some good documentation on it out there. Here's the first function I wrote:

public long fibo(int n){
    if (n <= 0) return 0;
    if (n <= 2) return 1;
    long ret = fibo(n-1) + fibo(n-2);
    return ret;
}


Here's the new, much faster function :

public BigInteger fibo2(int n){
    if (n < 3) return BigInteger.ONE;
    BigInteger fn = BigInteger.ONE;
    BigInteger last = BigInteger.ONE;
    BigInteger last2 = BigInteger.ONE;
    for (int i = 0; i < n-2; i++){ // n-2 because first 2 are 1
        last = fn.add(BigInteger.ZERO);
        fn = fn.add(last2);
        last2 = last.add(BigInteger.ZERO);
    }
    return fn;
}


I had to use BigInteger (in the java.math package) because after about 100, "long" couldn't fit the result anymore! That's a big F@#%$!$#!ing number that a long could hold!! But not big enough.

For mathematical clarity, there is a formula out there, called Binet's formula, that calculates the Nth fibonacci number.

F(n) = (a^n - b^n)/(a - b)

I'm having problems with types, I can't get it working.

But for the fun of it, here's some output:

For #40:
102334155
Fibo2 for fibonacci #40 took 0 milliseconds.
102334155
Fibo for fibonacci #40 took 4811 milliseconds.


For #42:
267914296
Fibo2 for fibonacci #42 took 10 milliseconds.
267914296
Fibo for fibonacci #42 took 12955 milliseconds.


As you can imagine, the second one in the results (the function simply named "fibo") will be an unbearable burden to the rest of my experiment. So, I'm getting rid of it and will show you some major f@#%R@#ing numbers produced by "Fibo2". Check it out.

176023680645013966468226945392411250770384383304492191886725992896575345044216019675
Fibo2 for fibonacci #400 took 10 milliseconds.


WHAT IN THE WORLD IS THAT NUMBER?!?!?!?!!! Holy crap!! And 10 milliseconds. Let's see 500!! I wonder when BigInteger overflows... maybe never.

13942322456169788013972438287040728395007025658769 7307264108962948325571622863290691557658876222521294125
Fibo2 for fibonacci #500 took 10 milliseconds.


(I had to put a space in or else my website would be all f'ed up... but that's one number continuous)

That's incredible. "For my next job, I'll take a salary of $Fibo(150)." That's huge :) Anyway, I had fun. I want to see how far it will go before blowing the hell out of my computer, but that will be an experiment reserved for tomorrow at work :) It's not my computer then.

What to do with a bazillion dollars?

I don't ever wish to win the lottery or be rich or anything like that, but if I did (if you don't play, you can't win...), I thought about what I'd do with it. Obviously, the smart thing to do would be to invest it somehow. Somewhere. I'm not too smart financially, so I wouldn't go with stocks or bonds or other financial things that I have absolutely no idea about. The obvious thing for me would be to go back to school. I am always buying books and learning stuff, so it's obviously obvious :)

Where I would go to school would be two places. Some kind of video game school (like Full Sail), and an elite institution for technology, namely, MIT. I think I'd go to MIT first, though. I'm all about getting a PHd from MIT. Besides the fact that it rhymes, that pretty much says "I know what the f@#%@# I'm talking about." I would make complete use of my time there. I'd be lost for the first year (it's been a while since I've done ANY math), but if I had money, I could just hire tutors for $100 an hour, and they could teach me math. It would be easy. I have a math mind, but it's not like riding a bike.

MIT first, also, because I'm more interested in Computer Science than I am in any one field of it. Creating video games uses multiple fields in CS, but it's not the whole of Computer Science. It's math, 3D graphics, artificial intelligence, and algorithms for other things like physics. You see physics in games today, but it would be neat to see other sciences, like Chemistry :) But that's going down another road.

Anyway, if you have an extra bazillion dollars lying around, I wouldn't mind having it :) I must be a geek, because I can't even think of anything else that I'd use it for.

VS is BS

When it comes to Integrated Development Environments (IDEs), I am a knowledgeable critic. Having used quite a few (Borland C++ 5x, Visual Studio 6, Eclipse, NetBeans, Visual Studio .NET, 2003, 2005, etc), I know what features I like and expect. My day job consists of me primarily using a Visual Studio of some sort, and lately it's 2005 (Whidbey). So, the statement that I am about to make is absolutely true. It sucks.

When I first heard about it, I heard that it would have features like "Refactoring", a cool debugger, "smart" IntelliSense (I know, it's called IntelliSense, yet it's incredibly unreliable), and... you know, I really don't know all the features. Having used 2003 for so long, and now using 2005, it doesn't seem to be that different. However, hearing some cool tech terms like "refactoring", I became excited that, finally, work might go faster, I could get more done in shorter amounts of time, finish projects early by factors of weeks, get 15% annual pay increases, and retire by the time I'm 30. However, none of this will be happening. It sucks.

In my free time, I primarily use Eclipse. I must say, a bazillion times, that it's the best IDE out there.

Let me define refactoring. Refactoring is taking existing code and doing stuff with it, whether it be renaming a class, variable or a function (and automatically updating all references to it), generating properties for member variables, and stuff that generally has to do with renaming, but it can also be quite advanced. Say you have a class with a few public functions in it. Refactoring could mean taking that class and extracting an interface out of it. Refactoring could also entail creating a variable out of a "String" constant in your class, and externalizing it to a file, so that you could then change it without having to recompile each time. You can have a bunch of lines of code that you could foresee yourself using over and over, so you would want to extract those lines and put them into a function, and the function signature would include any variables (and their types) that the code is using to be passed in as parameters. This is also refactoring.

VS 2005 simply fails in what I need it to do most. At the top of that list is generating properties from private member variables. Most, particularly good, object oriented programmers who like to save time in the long run will follow "patterns". Google "Gang of Four" for examples of what I mean. Three patterns that save a lot of time are the following:

Business Object Pattern.
Data Object Pattern.
Data Access Object Pattern.

Business Objects perform business logic on a data object (which holds data) and these are stored and retrieved to/from a database through the data access object. Simple. The one of these patterns that will have a lot of properties is the Data Object. These hold the data, and as such, you should be able to find out what the data is that it's holding, and you should be able to set those fields to different values.

If you have access to these two IDEs, try the following experiment. Copy these two classes into your IDE as new classes, do a refactor, and get it to generate all of the properties (in Java, getters and setters) for the variables in the class, and see which one is quicker.

Java code:
import java.util.Date;

public class DataObject {
private Integer id;
private String name;
private String description;
private Date modified;
private DataObject parent;
private DataObject[] children;
}


C# code:
public class DataObject {
private Int32 id;
private String name;
private String description;
private DateTime modified;
private DataObject parent;
private DataObject[] children;
}


You'll find that Eclipse's goes faster, simply because you can right click, then click "Source -> Generate Getters and Setters", click the "Select All" (or Select "getters" or "setters" [giving the option of making every property read only or write only]) button, and click "OK". Done.

You'll find that VS 2005 is F@$^%ING RETARDED!!! You have to highlight a certain field, one field at a time, click "Encapsulate Field", then you get no option to only generate the get or set parts of the property, and it comes with the option to "Update References" of either just the external references or all of them. You know where I'm going with this. If it's a PRIVATE FIELD, THERE ARE NO EXTERNAL REFERENCES!! Not one. You can just see the lack of care put into this aspect of the product. Why even include it? I just type them now, because the project I'm working on has 37 (THIRTY SEVEN!!) projects that it would have to search to encapsulate ONE lousy field to update references to A PRIVATE VARIABLE. And it takes forever on my machine, AND you can't F@#%&#%&@ turn OFF the "Update References" option?!!?!!

It's really retarded.

Some other gripes. Intellisense isn't any smarter. At first, I thought it was, but it's not. Say I have a class like this:

public class Mulder { // x-files rules
public Mulder(){
this. /* <---- at this point, it drops down a list of accessible variables, which would include "memberVariable", but it doesn't! This is because it's defined *BELOW* the point at which you are typing (the constructor in this case), and VS 2005 has no idea that it's even there!! Try it yourself. */
}

private String memberVariable;
}


I have other smaller gripes on Intellisense, like it not selecting a String or a function that returns String when you are assigning something to a String variable.

String scully = this. /* <-- doesn't go to the first string */

This is somewhat understandable though, as every object in .NET has a "ToString()" function on it, which is really just used for debugging. It doesn't perform any better with other object types though.

Anyway, I love Eclipse and open source, but knowing of these great features just spoils every "feature" that Microsoft comes out with.

Readonly Classes

This is a quick one before I head out to the Great American Pub tonight with some friends. I was writing a way to make simple input screens based off of the information in Dumb, when I realized that when I got that information, I had access to the whole class, and didn't like it. Basically, something that's using the information doesn't necessarily need to manipulate it. So, I abstracted out those classes into interfaces with selected properties that are readonly. The problem was this: I had to update all the references to the class to be references to the interface. It took forever, but I eventually got it, and after touching practically every class in Dumb, it's now almost up to date. I still have to create an "information getter" interface so that I don't have to have direct access to every method in my engine class (I only need to be able to select, insert, update and delete, for now), whereas the engine class has methods in it to create tables and generally access a lot of different stuff that a simple inquiry class doesn't need access to. Also, the engine already implements an interface, but it's a 1 to 1 implementation (meaning, it is just an abstract API interface so you don't have to know which implementation of the engine you are using... I can have multiple engine implementations and just swap one in [like a CachingEngine that doesn't hit the database everytime if it already loaded an object]). So, I'll have to add another interface on top of the engine interface

e.g.
public interface DaoEngine extends InformationGetter

that has just methods to get that info out. Names not final.

After that whole thing's done (including making the automated data input screens), I can work on Attachments. That's gonna be awesome.

Attachments

This post can also be subtitled "The Philosophy of Computer Science, Part 1.1". It's a new idea I'm playing with. It's not a new idea, really, it's derivative of a very cool concept in Computer Science called Aspect Oriented Programming. It's a pretty abstract concept. Basically, the typical example used is logging transactions on an object (I know, that description is very abstract also). So, say I have a bank account and I want to log my transactions, I can just flip a switch, sorta, and now my bank account is emailing me whenever I deposit or withdrawal money. But, what if now I want to deposit half of the money in a savings account when it's deposited in my checking account WITHOUT modifying ANY banking code?! Impossible, you say? They key here is that I don't want to go into the "deposit" function on my bank account object and enter stuff to deposit half of it into my savings. If you designed the system using an AOP container, this would be simple. What if I wanted to log AND deposit half into savings on a deposit into my checking account? I would just write a class that "intercepts" a call to deposit money into my checking account and takes half and puts it into my savings account, then continues the call to deposit the money into my checking account with half of the original value. Of course, if I was dishonest, I'd just deposit half into savings and then the original amount into checking!! But, that's not honest :)

So, AOP is very flexible. What I'm developing is a twist, though. It's for objects on my website, and it's mostly to do with data, rather than "processes" (like, before I deposit my check, take half, put it in savings, then put the other half into checking). So, to be more in line with data, and to be sorta AOP, what would it have to do?

Pretend I have a News object (I do, you're reading it), and that news object, right now, has a title, a date, text, the user who wrote it, and the categories it belongs in. What if I wanted to add a file to correspond with the news that I could upload and it would automatically show itself with a little paperclip (signifying an "file" attachment), and the filename next to it, with a link to download it. I don't want to program the news so that every news item could potentially have a file attached to it. You'll see later that by attachment, I don't only mean "File" attachment, like you send with an email. What if I want to allow other objects to have that same type of attachment, i.e. a file uploaded and shown under that item? I'm not about to change my whole, very well designed, table and object structure. I'm way too lazy for that.

Another attachment possibility for News would be a "History" attachment, so that whenever I update a news post, it puts an entry into a history table, and I can view that news' history. Another one would be a "View Count" attachment, so that whenever that news item is viewed, I increment a field for that news item, and that value shows under the news in a label that reads "Read 4 times". What if I wanted to put security on a certain news item? I could make a "Security" attachment that ties into my current security system and checks to see if the person viewing the website should be allowed to see that news.

The main thing here is that I don't know all of the possibilities for the future. That's where Object Oriented programming and Aspect Oriented Programming form a perfect marriage. I can program a new attachment and add it into the system, then any object can use that attachment. One downside of this design right now is that for every news item I enter, I will have to select, each time, what attachments I want. For some things, it just makes sense. Like, I could turn "Comments" into an attachment, but for most news items I will want to allow comments, so I would be adding that to every news item. The upside, in contrast, is that some objects were not designed to be commentable. I could make Content commentable this way (click "Your Site Rules!" for a Content example).

One thing I could do is have a global attachment for objects. News could have a global attachment of Comments, then a local attachment could be a file attachment for a certain news item.

One pretty big downside of this system is this... it's website rewrite time!! Yup, the whole website will have to be redesigned. The data, however, can pretty much stay how it is. That's good, because I decided on this design because I didn't want to change the data structure! I'd hate to lose anything I wrote, I love reading my own stuff ;-)

I can hardly stay awake right now though. Til tomorrow.