- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Maybe the execute query returns an exception.
Admin
Interesting detail, especially as right now I'm building a system that does use Austrian SSNs as keys. But then - how DO you correctly find identity between two persons entered by different people?
Admin
While I agree that its possible that you do need every column I think the Select * is like a goto.. sure its there and it can be used correctly (or atleast nonhorrifically) . Listing out the column names are the plus to me where you see a minus. Typos should be an error and if columns are removed then the code should complain about not finding the column. Adding columns rarely screw things up though if you are naming the columns. Using Select * makes it uncertain. Misspelled column names will probably still be caught with an exception (in java) or worst case just always give you a NULL value (php and the like). The NULL might cause enough problems to remind you that "Oh yea I removed that column and need to change my code" if you're lucky. Using Select * and adding columns might be okay unless other WTFs are in the code like using the column index to get data. In that case adding columns might make the data wrong but not enough to break anything. So using Select * can cause hard to spot errors in code while enumerating the column names makes errors very loud (atleast in java since I have the most experience with that). And I think that loud errors are better than silent or hard to spot errors. Hence to me Select * signals possible trouble in the future and should be avoided.
Admin
this code merely plants the seeds for may other WTFs to grow from....
Think of all the classes that have to do something like...
/*******************************
WTFDatabaseHandler dbHandler = new WTFDatabaseHandler();
Object aRecord = dbHandler.findRecord("some_table", 55);
if(!aRecord instanceof ClassNotFoundException){
//Yay!!! I can do stuff....
} else {
//do i return the exception here? hmm....
//no record returned?
//database meltdown?
//end of the world is coming?
}
/********************************
I'd like to see some of the code that has to work with this crappy 'findRecord' method...
Admin
(It would be nice if you'd answer the questions! I'm quite curious to hear about the design decisions you'd choose for those tables)
Also -- not a good argument: "lots of people don't define constraints properly, so I don't bother -- I avoid them completely!". Lots of people don't comment their code properly or use appropriate datatypes, do you follow the same logic and avoid those also?
And, again, a natural key doesn't have to be a department's name or a department's description or anything that might change. It might even be a number. Just because a key is natural doens't mean it has to be a varchar(255) descriptive text! You are still allowed to store other columns in your tables and to join to them to present names and descriptions of your objects even if you don't use identities!
We once had a consultant in the office who kept confusing "identity" with "primary key" -- and refused to acknowledge that any table w/o an identity column could have a primary key.
Admin
I'll go ahead and take a shot at this, with my standing being that in general non-identity primary keys should be avoided. There are cases where they could be used, but in those cases an identity can usually be used as well.
This is a case where a non-numeric key could very easily be used. However, an identity field could also be used for the primary key. Just an example schema: States(StateId, StateAbbreviation, StateName). Joins could be done on the identity field, StateId, and they would be less expensive than string comparisons. Either way in this case, it's not a big deal.
Ideally, the unique code given to the employee/customer would BE the identity column when they are entered in as a new employee/customer. But either way,
Employee(EmployeeId, EmployeeCode, FirstName, LastName, etc)
I'm not sure what GL stands for(although I'll probably smack myself when you tell me later ;) )
Example Schemas:
Employee(EmployeeId, FirstName, LastName, Address, etc)
Skill(SkillId, SkillName, SkillDescription)
EmployeeSkill(EmployeeSkillId, EmployeeId, SkillId)
Admin
Well that is patently retarded. Please remember though that not everyone of us who would, in general, rather use an auto-increment ID column for a primary key instead of a natural primary key is likewise retatrded.
Instead of hijacking this thread any further with this debate, I think this thread, which has already been hijacked with this debate, should be hijacked further.
Admin
It could be a big deal. Lets say the company expands internationally. Now, you need to modify specify what country the code belongs to If you used the state abbreviation as the key, you are most likely going to want to change the primary key of that table. If an identity was used, you can just add the new columns. The existing records that referenced the US states are completely unaffected.
Now, what about a case that I am working on right now. Without getting into the requirements too deeply, we have a need for some very focused custom mappings from one thing o another. We don't want to create a new table for each mapping, and we don't want to hard code these things. We also don't want to denormalize other tables that are semi-related. So I am creating a normalized table with a number of columns where the PK is all of the columns except one. Essentially the columns say, who I am, what I'm doing, what my input type is, what output type I'm looking for and in and out values.
There shouldn't ever be a need for other tables to have foreign keys to this one and I can't think of any reason to add an identity column. Would you argue that I should do it anyway? I don't really have a good reason why I didn't do it the other way other than laziness.
Admin
In my opinion, one of the primary reasons for using an identity field is for foreign key references in another table. If you can say with a reasonable amount of certainty that it won't be used as a foreign key, I wouldn't personally see an issue with leaving out an identity key.
Admin
I will try (briefly below).
You don't seem to understand, this wasn't designed in the first place like this, it evolved into this horric state over time. When it was first created, I guess the developer thought like you and had one column unique identifier. But then it turns, the business rules changed and we organized everything in to business units, and different business units wanted the same unique code... OUCH. Then we get categorization of this table so that each business unit for each category can share the unique name, but unfortenately the category table had likewise been improperly designed with a two column unique key. Viola, we now have the horrific table design that I was forced to deal with. (Btw this happened over years and many developers).
My point is that it can be really hard to tell what users will eventually want, I don't like adding unnecessary constraints to make a database look "cleaner", when my ORM will abstract all that crap away anyways. Not to mention you can do nice abstraction and generic helper routines if you store keys in a consistent way. This can of course be done using a Object Key model, but its harder.
Why are you storing the US states? If it is just for UI drop downs? If so I would probably use a more generic lookup table. Then I can put a nice abstraction around handling of the Lookup objects for conveniently handling lookups based on a lookup type code.
Will that unique code stay unique? Or will the business process down the line start reusing code of expired users?
I am not well versed in General Ledger business rules, so I can't really comment.
Absolutely provide ids, the employee name, and skills are both likely to have changes.
Admin
I'll say it again - executeQuery NEVER RETURNS A NULL. Thanks for duplicating the WTF!
Admin
I'll ask again, how do you know?
Admin
5. The ClassNotFoundException would only be raised if executeQuery did something like this
try{
//foo
catch(){..nocode..}, because database exceptions would have been thrown. So unless you wrap executeQuery in try(), why bother checking for null?
6. Why return a type Object if this is data? Shoudln't the return type be of type DataSet?
Admin
The function itself is a WTF! While I am all for decomposing programs down into a lot of small functions and abstracting methids as far as possible, in this case there is a loss of abstraction from using this function. The caller has to discard the information about both the actual parameters of the query and the query's results. Furthermore, the incorrect exception handling means that the function swallows the intended exception (and would be using an incorrect exception type anyway), and it fails to either handle of declare the possible exceptions from the executeQuery() as well - hell, it shouldn't even compile like that. If they'd simply written out the damn query execution (as a parameterized query, of course) where it is being used, it would actually be a lot clearer.
The saddest part is that it looks like the reason he returns an Object rather than a RecordSet is so it can pass either a ResultSet or a ClassNotFoundException. If the coder had known what they were doing, they would never have done it that way.
Oh yes, and it makes no reference to the instance variables of the class it belongs to; it's a static method in an instance method's clothing. Since it isn't mentioned what sort of class it is written for, I assume it should have been a static function (and probably a private one at that), though I wouldn't be surprised if the objects of the class in question would already have the table name in an instance var. Does this coder actually know Java, or OO programming, at all? Apparently not.
For that matter, how is that executeQuery() supposed to work, anyway? It's called as if it were a global function, rather than as a method for a Statement object. Java doesn't even allow global functions! There's no way this would compile. Perhaps that was the instance variable it should have been referring to, eh?
Admin
That's only true for instance and class variables. Local variables have no default initialization.
Admin
I'm not sure if this is what you mean in the above, but executeQuery is apparently a member of the instance or class.
Admin
Jeff Wrote: 'Don't get me wrong, there is a time and a place for everything. And some tables (most often transaction tables or tables that take lots of raw, unvalidated user input) should have identities as the PK. But not every single table in your database for goodness sake!'
I would say that you have gotten the rule backwards. Most tables should have identities as the PK, but there are exceptions.
Admin
<voice style="two guys in a british pub"> Brillant! </voice>
Admin
Annoyingly, this is how a lot of code I have to maintain works. Just substitute NullPointerException for ClassCastException.
Interestingly enough, if that's actually what is done, the exception message from that would be something like:
"ClassCastException: ClassCastException"
Admin
I would definately agree with this.
Admin
Well if he extended a Statement object it would exist as a method and could be called the way that its listed... thats what made me wonder about that possibility.
Admin
Ahh finally some java on this site :)
Yes, I used select * allot in my webform code. Maybe thats because I've designed the tables I'm quering so I need every column in a given record anyways. I don't consider this a wtf.
I say that setting a new obj or var to null to initialize is fine, as long as your checking against it being null. However, in this case it's borderline WTF and it's a good clue as to the authors skills, they probably initialize all their objects to null like this which could definately cause problems.
Returning an exception as an object, wow, I've never seen that before! Lol, glad I don't do that. Yes, definately a wtf.
The call to method: executeQuery(String sql) could be a wtf or not, depending on what that method looks like. That exectuteQuery could be creating a prepared statement and opening and closing connections to the db, or even validating the table name. Without a wider context of what this little gem is doing it's hard to say.
Concatinating (sp) an int into a string directly, no problem with that in java, no wtf there.
Using "i" as the int name, not a WTF (in this case) imo, it's a local variable name(local to that method only). However, in general practice it's not good form and this falls into he same category as initilizing to null. Based on these two little "clues" I bet there are some coding doosies by this author that trump this example.
Another little style choice, naming the string table should be "tableName", but it's a minor niggle.
Admin
It looks as if the guy read this article and came up a way to eliminate the "multiple exit points" problem.
Admin
I know, lets abuse the DUNS number.
Admin
Thanks for posting that. I knew there was a reason I think Joel is a maroon.
Admin
BTW, the select * is merely defining the width of my result set, a WHERE clause is a must with little exception (no pun intended).
Furthermore with a little more reflection on this, setting the object to "null" in this case is probabaly retarded as excecuteQuery won't most likely be returning a null. But without seeing said method, there's no way to really know what it's returning.
Admin
1) Declaration of table and i not final.
2) Assigning a local (r) to null.
3) Redundantly assigning a local (r).
4) Assigning to a reference of a more abstract type (java.lang.Object) to an interface type (java.sql.ResultSet).
5) Passing a parameter (table) of a public API to the database (i.e. potential SQL Injection vulnerability).
6) A one line statement block not surrounded in braces.
7) Failure to restrict scope optimally.
Everything else that has been mentioned is an extrapolation that assumes too much context (perhaps is could be provided?).
Admin
If executeQuery could return null, would that make setting the variable to null before that less retarded?
Admin
Wanna know something really geeky?
It's actually 'Three Letter Abbreviation'. An 'acronymn' is an abbreviation that forms a word, like 'laser' or 'radar'.
Grammar geekiness rules! [:D]
Cheers,
mabster
Admin
Jonathan -- great job avoiding answering every question. The one you came closest to actually attempting to answer (the last), you still didn't. I didn't ask what foreign keys you would use to relate the EmployeeSkills table to the Employees and the Skills tables, I asked what the primary key of THAT table would be.
Clearly, this is not the proper forum for an intelligent database discussion!
Admin
http://merriamwebster.com/cgi-bin/dictionary?va=acronym
http://merriamwebster.com/cgi-bin/dictionary?book=Dictionary&va=abbreviation
examples from these:
acronym: FBI
abbreviation: amt (for amount)
Admin
Admin
Here's what I think is going on.
Somewhere in this class is a method along the lines of:
public ResultSet executeQuery(String query) {
Statement statement = comeEstablishedConnection.createStatement();
ResultSet record = null;
try {
record = statement.executeQuery(query);
return record;
}
catch (SQLException e) {
return null;
}
}
The author of "findRecord" just takes the above written piece of amatuerism and builds on everything that's wrong with it.
Admin
*kicks self* Oh, yes if course, I should have realized, especially since it was even mentioned earlier. Never mind.
Admin
The nice thing is with a "numbered index" is luckily nothing ever attempts to stop you from having
1,MA
2,Massachusetts
3,Mass
4,Massachusets
5,Ma.
6,Mass.
in your table .... No pesky constraint or primary key violations to worry about!
Why would you want to make any attempt at the database layer to enforce only 1 value for massachusetts, right!?
It is April 1st or something?
Admin
No it wouldn't :)
Just thinking out loud.
Theres a big difference between something that isn't "proper", or bad practice from a style standpoint and something that is just flat out wrong. To me, real WTFs are those things are the latter.
Setting this to null in this case is just unecessary but not really harmful, as if this needed something else wrong with it to make it more borked up then it is.
Admin
The real WTF is how the editor can claim to be a programmer and never have heard of LOC before.
Admin
The nice thing is with a "numbered index" is luckily nothing ever attempts to stop you from having
1,MA
2,Massachusetts
3,Mass
4,Massachusets
5,Ma.
6,Mass.
in your table .... No pesky constraint or primary key violations to worry about!
Why would you want to make any attempt at the database layer to enforce only 1 value for massachusetts, right!?
It is April 1st or something?
Gosh dangit, all of you, can we stop yelling at each other and calling each other names? This is a subject of great interest to me and I'd rather learn from you people than watch you bicker! ;)
Jeff, please correct me if I am wrong. Let's say you don't have a auto-increment primary key on your States table. I'm assuming you would rather use the name of the state? If so, you could still have craptastic data, e.g.
MA
Massachusetts
Mass
Massachusets
Ma.
Mass.
Just to refrain from using an auto-increment primary key alone won't give you any "pesky constraint or primary key violations to worry about" in this situation, will it?
Something I have seen quite a bit from those who don't condone the use of meaningless primary keys is the assumption that those who do are incapable of using additional and necessary constraints. The mere fact that I might use an auto-increment primary key on a table does not necessitate that I let the user's do as they please with the meaningful columns in that table all slapdash and willy-nilly. I can have a table States(StateID, StateName) such that StateID is the primary key AND StateName is unique.
Admin
My nickel's worth....some of it's already been said, some of it disagrees with what's been said...
First a correction to people that are saying Object r = null; is bad because it should already be initialized by Java. Java doesn't work that way. Variables and references declared inside of a method are not automatically initialized (at the class level they are). The author could have condensed the two lines together though as in Object r = executeQuery....
On to my WTF's...
1.) Returning an exception....that amuses me.
1.a.) Returning Object doesn't bother me as much, depending on the context in which this is being used. Maybe Object is the most concrete thing that can be returned in this case. So it may be a WTF and may not be.
2.) Using ClassNotFoundException....seems like a RecordNotFoundException to me. At least he's not propagating SQLException all the way out to the caller.
3.) Exceptions should be for exceptional conditions...not finding a record is not exceptional (and in many cases expected). As a personal rule, my methods named "findBlahBlah" do not throw exceptions if they can't find it. My rationale for this has been...the find method doesn't have enough information to make the determination whether it's an exception....e.g. "System please find me this record if it exists." "Oh good, it doesn't exist, so we can execute this functionality." or "Ok, I guess we should create it then." Whatever method calls findRecord should make the determination as to whether it's an error condition.
4.) Not using a StringBuffer for creating the SQL. I read somewhere (can't remember where off the top of my head) that if there are more than three things being concatenated, StringBuffer will perform better than concatenation. Less than three, the cost of allocating the StringBuffer and converting it to a string is more expensive then allocating the new strings on each concat.
5.) Using i as the variable name for an id.
6.) Returning an exception....it's so bad it counts twice.
7.) Not condensing Object r= null; and the following line into one line.
8.) I have a feeling the author of the executeQuery method is swallowing the exceptions...no try catch surrounding executeQuery and no throws clause in the declaration (unless he's throwing an unchecked exception -- then I retract #8).
Also, did anybody notice that the there are two posts hanging out above the original?
Admin
Agreed, this is why I'm from the school of use both dumb keys and business keys. a dumb primary key makes life so much easier when having the computer look up the data or making foreign keys. At the same time, the business key (alternate key whatever the name you learned it as) is used to constrain the data.
I love it in a system that uses "natural" keys to enforce RI...as the schema evolves you start getting 7 or 8 part keys, and then someday someone comes up with a need for adding a 0..n relationship so now you're looking at an 8 or 9 part key and so one. If every table gets it's own dumb key and business key, then the business key in the descendant table can simply include the foreign key along with whatever else is required.
Second, when dealing with data warehousing...it's a good idea to have both. Otherwise trying to uniquely identify a customer without using a dumb key becomes a real pain...usually something like...fname, lname, suffix, middle initial, street address, city, postal code, state/province, and country. No thanks...define an AK with all that crap defined and provide a customer_id so my code is nice and simple.
Also, if everything in the system uses the same key type...i.e. a long or a UUID it's a whole lot easier to write generic lookup code (i.e. test for existence, retrieve a single record, delete a record etc.).
Admin
This is sufficient reason in and of itself to use a unique ID for your primary index.
Just wait til you have a database with 100K records in a table where the primary index has 4 fields. The joins alone are obnoxious enough to make it worth skipping, let alone the more serious issue of referential integrity issues.
Admin
I say, if you're going to play CODASYL, you may as well use CODASYL. It becomse so much easier that way because you get all these great things like functions to help you walk pointer-chains ...
Admin
Geez, there's your WTF right there. The identity field shouldn't be visible to the departments--that way they can have their own non-unique department codes.
Admin
Remember, kids, all acronyms are abbreviations, but not all abbreviations are acronyms. Quick test: in set theory, how do we define that relationship?
Admin
The only mess we have here is your inductive reasoning.
Meaningless keys are clearly advantageous over meaningful keys, which you advocate. You are crusading against the superior option. As soon as you couple record identity to some external source, you introduce a dependency which possibly causes you to rearchitect your entire key structure when that source changes.
There is no reason why a database with a meaningless key structure can't be as tightly constrained as your vision. Or do you honestly believe the only way to enforce unique constraints is via a primary key?
Admin
Would this not be better written as:
<FONT face="Courier New" size=2>Object obj /*= null */;
try
{
obj = someFunctionOrAnother(...);
</FONT><FONT face="Courier New"><FONT size=2>} catch {
obj = null;</FONT>
</FONT><FONT face="Courier New" size=2>} finally {
if(obj!=null) doReleaseStuff(obj);
}</FONT>
Or more likely:
<FONT face="Courier New" size=2>Object obj = someFunctionOrAnother(...);
try
{
...
} finally {
doReleaseStuff(obj);
}
I'm not sure about Java, but I cannot think of a good reason to initialize an object to null... ever. Maybe someone could provide a better example?</FONT>
Admin
Here is the biggest WTF for me. Quoting from the Java API documentation
ResultSet
object.ResultSet
object that contains the data produced by the given query; nevernull
so by this, the if (r== null) line and subsequently r = new ClassNotFoundException() will never execute. You're either going to get an empty dataset, or one with records in it. You'll never get the exception object back.
Admin
Well few things that i figured out were:
a)in line 3 you are concatenating Strings, "select * from", and "table" are static strings. What internally is being done is that four objects are created everytime the query string is formed. So if you have 1000 query you would have the overhead of creating 5000 objects , i.e. 1000 for each String + 1000 for each object returned. Using StringBuffer will be a lot less resource intensive.
b) we r returning <font>ClassNotFoundException</font>()... how can the caller figure out whether it is returned by java or the database??
It would be great if the author enlightens us about the exact nature of those >7 errors
Admin
First of all, I didn't read all of the posts.
Secondly, there's nothing wrong in returning an exception, and here's why:
If you use the Invoke method to invoke methods from an assembly you loaded into memory (like a plugin) and this method throws an exception all you will ever get back is 'Invocation threw an exception' or some such message. The original exception gets lost. So you declare the return type as an object, return either what you want, or an exception. Then you can check after your invoke if the return value is of the exception type and throw the right exception.
I've used this in various places, but mostly only to propagate real exceptions ie:
Try
...
Catch ex as Exception
Return ex
End Try
Return RealValue
Drak
Admin
Ofcourse I wrote the above without noticing that everybody seems to agree that the original code is Java. I don't knwo if Java has assemblies, or Invoke methods etc. So if it does not, ignore the above post, unless you want to know why you might want to return an exception in (vb).Net.
Drak