- 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
ERR: FILE_NOT_FOUND
Admin
Admin
Admin
"You must be a stranger in these here Parts!"
Admin
Admin
http://www.youtube.com/watch?v=OTzLVIc-O5E
Admin
Admin
We're a little limited here by the deliberate terseness of the write-up, so just for once let's think in terms of design rather than minute code analysis. Waving a pointy stick labelled "normalisation" or (God help us) "O-R mapping" is little more than willy-waggling.
We don't know anything at all about the application, so it either regards "parts" and "assemblies" as identical (the "catalog" model in an earlier post) or as distinct (almost anything else.
If they're identical, you don't need the stupid flag.
If they are distinct, you need to express the distinction somehow.
How do you do that? Well, you could use a (presumed) boolean column, as here. Or you could use a "discriminator" column. Or you could use one or more other tables.
If the column is boolean, then you are FILE_NOT_FOUND^H^H^H^H^H^H^H^H^H^H^H^H^H^Hfucked. The minute you're asked to update the design for, say, "sub-assemblies", you have to rewrite the schema and break every program that relies on it.
If not, then you're reducing an arbitrary relationship between entities/objects to a simple, flat, enum. This is dumb in either OOP or relational terms.
But to return to K Klein's assertion. It is unlikely, I think, that an Assembly would be modelled as a subclass of a Part -- rather, the other way around. However, you can substitute "penguin" for "Assembly" and "flock" for "part", and it doesn't really matter. I'll go with D being a subclass of B as case (1), and C (Assemblies) being a collection of D (Parts), where C and D are both sub-classes of B as case (2).
(1) Sorry, but if I'm using a factory in OOP code to work with B and D, I want the buggers in separate tables. No O-R mapping problem here. One table, one class, and one Ring (oops, Abstract Factory) to rule them all.
(2) I definitely want separate tables here. The great thing about referential integrity is that I can use the database to add appropriate constraints (appropriate to the application, of which we know nothing).
In short, I cannot see a valid relational or OOP reason to come up with this monstrosity of a schema. It will certainly bite you in the bum further down the line as a maintenance programmer, or when scalability becomes an issue. The only reason to fall into this bear-pit is deadline desperation, and, frankly, I would rather gnaw my project manager's testicles off than face up to crap like this. Or:
Precisely.
And to the DBA who claimed earlier that C/C++/Java/.Net/whatever programmers shouldn't be let near database design: well, I'm sorry, but you're just plain wrong. This stuff isn't rocket science, you know.
Reading some of the comments here, though, you might have a point.
Incidentally, if the table is relatively small, and is only read and updated by a single thread in a single application, then there's a perfectly good argument for making it an XML document rather than any sort of an RDBMS application. Easy to validate with a schema, open to future requirements, and can be seamlessly communicated between various environments.
There. That should make some people out there very happy.
Admin
Agreed on the stupid column name, but having a discriminator column may not, strictly speaking, be the best alternative as it may miss changes that are taking place in the live environment.
Imagine an automotive wholesaler has a part number for an engine block (just the block, mind you, nothing else). Now imagine that the block starts shipping with a gasket and ring kit. So some staff member dutifully enters the components into the 'assebly_components' table in the database but due to poor programming on the data entry interface, or a typo on the part of the staff member (I know, both of those things never actually happen in the real world so my example's a stretch ;), the flag for 'isAssembly' is never set, even though the part's membership has actually changed.
Mr. Parts manager does a search for parts that are assemblies and the new engine block 'assembly' fails to come up. He yells at the data entry person, who gets fired, beats their kids as a result, their kids grow up to be druggies and one of them kills you in a failed mugging attempt, all because we could have used a
(your choice) and gotten somewhat more reliable results since those queries do not rely on data being updated in more than one table and also reflect dynamic changes to the makeup of any assembly.
/that said, searching a single boolean would be faster than doing cascading selects or joins on a large number of records... but I still like the guarantee I get doing it the way I suggested.
Admin
Admin
What happens when someone wants to make a part that is also an assembly? They should have a field called Part.IsPart. But you could also have things in that table that are neither parts nor assemblies. You can list those by issuing
SELECT Part.PartID FROM Parts WHERE NOT Part.IsNotPart AND NOT Part.IsPart
See how enterprisey it is already?
Admin
Admin
Perhaps, perhaps not, an assembly is described as several parts already built together. Yet, your proposed "IsAssembly" boolean field provides nothing special about assemblies.
If the company builds assemblies out of pats in its stacok, as value-added products, then it probably wants a separate ASSEMBLY table. An ASSEMBLY table shows all the parts that compose an assembly. The company can order new parts from its distributor based on how well that assembly sells.
Admin
I did something like this in Access once. But I just created a table called data. There is absolutely no need for more than one table in any application.
2 columns will do it: Data, Relationship.
Example of data: Smith, Last name of John 1234, Employee Number of John - See Smith $100, Per Hour Salary of Smith, John - See 1234
I used to work for SAP so I know what I'm talking about here.
Admin
Please tell me that was sarcasm
Admin
That just sound like you have a really really bad database design... Going down an 'one uber table fits all' would probably just add to your woes.
Admin
My guess would be that it's a varchar(4000) currently holding the values of "true", "false", "True", "False", "flase", "1", "0", "yes", "no", "y", "n", and "FILE_NOT_FOUND".
Admin
Admin
Read the OP, numb nuts. "The spare parts catalogue they were building..."
Well obviously they're not completely identical or we wouldn't be having this conversation.
Bingo.
Give us all a little credit Einstein.
What's the difference between an enum of ints and an enumeration of classes or tables. That's right -- bupkis.
Only a retard would make the general case (a Part) a subclass of the specific case (an Assembly).
I can't wait to see the SQL generated when your factory needs to query the database for all Parts (and Assemblies are Parts, right) matching a complex set of query parameters. Good luck optimizing that UNION pal.
Maybe if you took that testicle out of your mouth and listened to what your manager was saying you might learn something.
Precisely what? Self joins are precisely too complicated for you to understand?
Wow, I think my irony meter just blew a gasket.
Tip of the day for you: First think, then write.
I think that sounds like a fabulous solution for the residents of Imaginaryland who only have 5 spare parts, 2 suppliers, and 4 customers.
Yes, thanks for bringing this thread a much needed transfusion of WTF.
Admin
This person really seems to crawl under people's skin. It's very entertaining!
Admin
R
Admin
Admin
Real programmers.
Admin
Admin
Yeh, but he's kinda right as well..
Admin
Anyhow.. On the assumption that Assemblies are the same as parts, and these assemblies are stored in a warehouse and there is nothing special about them except their classification, a discriminator seems a perfectly valid design, Though IsAssembly would be a better name…
If, however the above is true, but assemblies and parts require different information perhaps a better design would be
StockItem {id, name, description, stockLevel.. other general fields} PK {id}
Part {id, part specific fields} PK {id} FK {id StockItem.Id}
Assembly {id, assembly specific fields} PK {id} FK {id StockItem.Id}
-- If Assemblies can only contain parts then this would do, otherwise if assemblies can contain assemblies then link back to the StockItem
Assembly_Parts {p_id, a_id} PK {p_id, a_id} FK {p_id Part.Id, a_id Assembly.Id}
If Assemblies are not parts, and at a stock level only they only store part, an Assembly is more like a 'bill of materials', as mentioend previously.. then perhaps something like
Assembly {id, name, description} PK {id}
Parts {id, a_id, name, description} PK {id}
Assembly_Parts {a_id, p_id, number_required} PK {a_id, p_id} FK {a_id, p_id}
Admin
However what happens if you have other things besides parts and assemblies, such as subsystems, and all you care is if the item is a "part" or not. Then while isNotPart is strange it does fit the best.
Admin
Then don't put things that are not parts, or treated as parts in the parts table. By stating that something is not a part, we are sayinhg exactly that.. It's not a semantically a part, and we don't treat it as a part
By creating a row in the parts table we are making a proposition that 'At some point in time, we have stocked part p1, and have 10 in stock'... Normally, correct me if I'm wrong we should only ever be interested in propositions that are true? Otherwise things can get quite absurd.
Now, that’s being quite obtuse I know, but why are we even interested in parts that aren’t parts if we can’t even be bothered to differentiate between what they are and are not.. e.g.
IsAssembly, IsSubSystem, IsCompoent..
Admin
...
Hey! I used penguins in my post:
Part.IsNotBananas Part.IsNotPenguin Part.IsNotMohorovičićDiscontinuity
Get your own ridiculous example!
Admin
ahh, but I used 'Badger', which trumps Banana on the ridiculous scale... when Badgers are involved, penguins just pale into insignificance on the ridicule scale. I stopped short of Beaver.
.
Though as an odd point, you design goes infinitely wide with ever possible IsNot as an attribute, while mine goes infinitely deep with a tuple for every possible false proposition about a part... I think your plan just tops mine, even with Badger… not withholding beaver.
Admin
Every time I read the comments on WTF, I curse the fates who made me an engineering manager.
Admin
:P
Admin
Try the drop down:
http://www.commodore.ca/manuals/parts/partsclass.asp
Admin
My thought was that it was single table polymorphism but with a poorly named/chosen discriminator. As for what's a subclass of what who knows? Maybe Part and Assembly are both subclasses of abstract ThingICanOrder. We'd have to know more about the design.
If it is single table polymorphism then the query given makes sense even though it's not so readable.
Single Table Polymorphism would seem to make sense here if we assume that the application spends most of its time querying the list of these things together, joining to them, or basically thinking in terms of "Things I Can Order". If the packing is done by moist robots (humans) on the back end then it may be the human that really gets to do the more complex logic to say "That's an assembly. Better assemble it".
There's still enough info in the database assuming other tables and maybe other columns in this table (maybe not) to relate assemblies to sub-assemblies or parts. You can design that as you will based on what requirement criteria you have.
It sounds like rarely updating info. I wonder about a link table (It's many to many after all) or if we allow assemblies of subassemblies of arbitrary depth there are some interesting data-warehouse techniques you can apply to make answering questions like "What individual parts make up this order" quicker. In fact a table with "ThingICanOrderID" and "ComponentPartID" as foreign keys back into that table would do it, especially if all Real Parts have entries saying they're made up of themselves.
Admin
[quote user="Grovesy And some propositions... The Part P1, can be supplied. The Part P2, can be supplied.
A1 Is an assembly
The Assembly A1, uses Part P1 The Assembly A1, uses Part P2
All makes, sense and everyone can understand the rules here... I hope the corresponding SQL DB design would consist of three tables. (Assemblies, parts, assembly_parts'
Except... according to their design, they simply have a Part called 'P3' which isn't really a part, it's an assembly.... Overall, not very intuitive.
[/quote]
If I understand correctly, their "space parts catalog" doesn't have to care much of what the assemblies are composed. They're just SKU, just like parts. Thus, it makes sense to simply put all in the same table. The distinction is only necessary when an user wants to see assemblies available, not just separate parts.
Admin
The spare parts catalogue they were building needed to manage assemblies – i.e. a grouping of parts – as well as individual parts.
clearly states assemblies are grouping of parts, so not an individual SKU
Admin
Admin
I take back my original soft-rebuke of your discriminator column suggestion and go with what I was originally going to say... it's a bad idea. It serves no useful purpose except to bloat a table. As other users and I have pointed out, there are better ways to track membership as an assembly (that will yield much more useable information). Also, there are many instances where you should track parts as a subclass of an assembly and similarly, track an assembly as a single part.
When I worked for an airline, our maintenance department had many items that would arrive pre-assembled, where the assembly was tracked by the hours it was operated. Additionally, the parts of the assembly were also tracked for the hours they were operated. Why? Some parts can be operated longer than others so, an assembly can be removed from an aircraft and the hours exceeded part can be removed from the assembly, saving money on replacing the entire assembly.
To return the aircraft to flight, typically another assembly would be inserted into the aircraft while the originally-removed assembly was repaired. Now, if during the course of repair, you find that you do not have a replacement part, you no longer have an assembly (and assembly stock is reduced by one); but you do have a collection of parts, each of which could be removed from the assembly under repair and placed into other assemblies (assuming there was life left on that specific part) if that part was needed on another aircraft. So the parts-stock is increased by an appropriate amount (but the individual parts' membership in that original assembly is maintained), the assembly is now essentially treated as unassembled (which is also a valid state), and you have increased the flexibility of your aircraft spares management system.
Now when you do get the repair part and insert it back into the assembly, not only do you need to track that part as a separate part, you also need to track it as part of a specific assembly (as well as increasing the assembly part stock by one and reinstating the parts-stock as active members of that specific assembly) to maintain the hour rating on the assembly as a whole.
So, yes, there are reasons to track assemblies as a simple part and ignore its composition, and there are other cases where it's just as important to not only inventory the parts makeup of an assembly, but to also track which parts make up which specific assembly.
Welcome to the real world and its practical example.
Are airline maintenance teams retards? No. Especially since they are following federally-mandated law. Are you? Could be. Especially since you can so definitively state that there is no reason to do exactly what they're required to do (and for good reason).
I'll leave you with three things; first, why not heed your own advice provided in your "tip of the day"; second, try to realize that there is a better way to make your point than to browbeat others on this site. Finally, accept that people will have different opinions than you. Sometimes they will be right, sometimes you will be right, sometimes neither will be right; unless you can calmly listen to and evaluate all positions, you will never grow.
Admin
I strongly suspect that I'm too prone to overstating my rhetoric, and that this is not necessarily a good trait when discussing technical matters on a blog. There are other occasions where I don't know what I'm talking about, or am drunk, or am otherwise confused. Those occasions would seem to be more a case for pity than for vituperative hate, though. I suspect that there are a number of borderline schizos who visit WTF every now and again.
But what the fuck. Very few of these people matter anyway, in any important sense of the word.
Admin
But that's just silly. And have you any guarantee that I can get it past BBCode?
An even better idea would be to pop up a dialog box that tells the reader to position the mouse behind the first 'F', drag it to the 'D', and hit ctrl-x or the delete key.
I'm still waiting on Ajax to provide that functionality, though.
Admin
(snippage)
(more snippage)LOL that whole thing was awesome. Thanks for the laugh caffeinatedbacon.
Admin
Admin
Imaginary programmers (those, sometimes shorthanded as "consultants") ?
captcha: yet again
ninjas
- quite imaginary programmers to me :-)Admin
See, as I hear it, they take all them little parts and make 'em into one big part!
SELECT * FROM parts as part1, parts as part2 INTO bigpart
Then they take that big part and cut 'em into little bitty parts.
SELECT * FROM bigpart INTO littleParts GROUP BY partID
And parts is parts!
(Man, I haven't thought about that ad in forever. Thanks for the nostalgia trip.)
Admin
I, as I'm sure others here do, get pretty tired of the "my way is the best/only way and if you don't agree 'u r dum'" attitude that prevails at times. The reason it takes so long to become a good programmer is precisely that there are so many different ways to do the same thing. The skill (art?) is in knowing what will work best in which situation, and often these stories don't present enough detail for anyone here to be able to make that determination (only to say that a particular attempt is not the best they've seen in the language of the example).
/Plus there's something about someone acting all uppity that makes me want to knock them down a peg or two (again, I doubt I'm alone in that respect).
Cheers!
CB
Admin
I disagree with all of the above, you stupid idiot. You're morally, ethically, and intellectually bankrupt, as well as pitiably wrong. You're also a grotesquely ugly freak.
Now, let's see who all forgot to turn on their sarcasm detectors.
Admin
Great! Those are faster since it's only using one table.
Admin
Admin
isNotpart is the name of the assembly. If the 'part' is an 'assembly', then isNotpart has the same content as '.part', indcating that the assembly isnotpart of itself, but is itself.
If a part is in more than one assembly, it will have two entries, as they are really different...
I think I have used a similar system before.
Admin
I only just got mine on in time!and damnationt to all you experienced bbcode users
And my tuppence on the WTF: this isn't a WTF, it's a hack. Or, more specifically, a kludge (in the British sense). Management want the catalogue to handle assemblies, and display them separately? You kludge it with a boolean - now you know what's what. If people want elegant software they should make sure they provide all the information necessary at the requirements stage (which, if I recall the software engineering part of my masters right, is somewhere near the beginning of the process?). You can always rebuild the db structure later once management have decided which other 5 features they want you to introduce in the last 2 weeks of testing.
This isn't pretty, but I'm sure it provided the functionality that was required, with minimal effort, in time for live launch. And hey, we're here to make what management wants happen, right?