|
CDP1802 wrote: Here and there he uses try and catch, but only to sweep the errors under the rug and go on as if nothing has happened. This man has never heard of OOP and he uses only static methods, probably because he also never heard anything about classes and instances.
I'm thinking we know the same developer here.
I figure that if you are a professional developer for more than 1 year you will run into code like this and know a developer who likes to make spaghetti.
CDP1802 wrote: Please believe me, the whole thing is a chaotic unmaintainable mess.
You're preaching to the choir here. I totally agree that it would be.
I wasn't, now I am, then I won't be anymore.
|
|
|
|
|
Our intern is a beginner. He makes mistakes, but he also is a smart young guy and really interested in learning. He makes progress and one day will be a good man in any team. I hope he does not read this
The fellow who wrote this stuff here has produced several websites, one more horrible than the next. There is no sign of learning at all. The first application of his we replaced was so bad that we wanted to post the complete source of it in this forum or publish it as a book (with critical annotations). In a way I pity him. Having to work without obviously knowing what he was doing and having to deliver something that at least appears to work on time must have been a nightmare. And every time I have to keep his stuff working without getting to replace it altogether I swear to drown him in the river should he ever cross my path.
I'm invincible, I can't be vinced
|
|
|
|
|
I got chewed out by a boss once, who said it's impossible not to write spaghetti code. So we should always write spaghetti code, and write the best spaghetti code we can.
I also got a bad review for the following:
1. Too many classes in my code.
2. Too much code.
3. The code is too structured.
Toward the end of my employment there, he made a rule that no bug fix, or new feature could go over three lines of code...
|
|
|
|
|
I hate when the boss is a complete idiot
|
|
|
|
|
What's so bad about if/else? I actually prefer using it in place of switch, just because switch is so ugly - you need a "break" after each case's statements? Seriously? I suppose it's not so bad in VB, where you're already using "end" statements instead of curly braces, but in C#, it just looks bad...
|
|
|
|
|
Only 9000 lines of switch cases?
I once found a database update function in a client-server app that had >10000 lines of if/else statements containing hardcoded table and database fieldnames, and field types. (I was supposed to fix it so it would reflect a recent change of the database scheme).
The person responsible for that later got hired by a head hunter. No kidding!
|
|
|
|
|
Stefan_Lang wrote: Only 9000 lines of switch cases?
No, that would just be boring. The switch was just a small sample from that spaghetti bowl. There is a Save() method, 1000 lines long, where he cobbles together a dataset. He begins by selecting some data from each table and then throwing away the results of his queries to get a DataSet with empty DataTables. Then he adds or removes some columns here and there and starts filling the newly configured DataSet with new rows and then finally tweaking the DataSet into storing this mess. At times I think this guy was a saboteur who deliberately tried to write the worst possible code. I could not come up with anything like that even if I wanted to.
I'm invincible, I can't be vinced
|
|
|
|
|
Adding and removing COLUMNS in a dataset while attempting to SAVE? Dear God, is he running ALTER TABLE statements in a save routine? Or just removing columns he doesn't actually want to persist?
|
|
|
|
|
Perhaps that's perfectly normal on some obscure planet where he comes from.
It rally truned out that he casually binds the dataset to a report before saving, so that you can print that out. The columns are added or removed according to the user's role and are perhaps added again after opening the report. Ahh, yes, he had to fill the some values into the newly added columns. He only does that in the first rows of the tables and ignores all others. That's also a common pattern in one of his other creations. He always assumes that datatables are filled with exactly one row, no more, no less. Anyway, he must have discovered that he needed an XML schema of the dataset, so he simply saves it after finishing his manipulation. Great idea. This way the schema is always accurate, no matter which route we took through the spaghetti code.
My best guess is that the report was added later and that he needed two or three slightly different reports, depending on the user's role. Anybody exept him would have clicked together a schema, created a typed dataset from it and added different queries to fill it for the different roles. Filling and binding it would have been something around 15 lines of code.
But don't worry too much about the database. Not a single table had a primary key and of course no foreign keys or other constraints. Why should he need them since he apparently believes that his queries always return exactly one row? I would not put it beyond him to simply reverse his manipulations in the dataset before saving. I honestly will not look if I don't have to.
I'm invincible, I can't be vinced
|
|
|
|
|
Behold!
I found something like this:
protected void Page_Load(object sender, EventArgs e)
{
List<Node> Stuff = loadStuff();
}
private List<Node> loadStuff()
{
List<Node> Stuff = new List<Node>();
someMoreStuff:
foreach (Node thing in Node.GetCurrent().Children)
{
Stuff.Add(thing);
}
Stuff = ShuffleNodeList(Stuff);
if (Stuff.Count < 100 && Stuff.Count > 0)
{
goto someMoreStuff;
}
return Stuff;
}
It worked... but I changed it so that it never happened:
protected void Page_Load(object sender, EventArgs e)
{
var Stuff = new List<Node>();
Stuff = loadStuff(Stuff);
}
private List<Node> loadStuff(List<Node> Stuff)
{
foreach (Node thing in Node.GetCurrent().Children)
{
Stuff.Add(thing);
}
Stuff = ShuffleNodeList(Stuff);
if (blablabla)
{
loadStuff(Stuff);
}
return Stuff;
}
Edit: So I changed it again...
protected void Page_Load(object sender, EventArgs e)
{
List<Node> Stuff = loadStuff();
}
private List<Node> loadStuff()
{
List<Node> Stuff = new List<Node>();
do {
foreach (Node thing in Node.GetCurrent().Children)
{
Stuff.Add(thing);
}
} while (Stuff.Count < 100 && Stuff.Count > 0))
return ShuffleNodeList(Stuff);
}
Giraffes are not real.
modified 21-Feb-12 11:13am.
|
|
|
|
|
Does C# do tail recursion natively? If not, there is an argument that the original is better, though it should be commented as such.
|
|
|
|
|
No idea... I assumed it was worse. Seen code of my senior colleagues using tail recursion too. (Monkey see, monkey do.)
Turns out it's not supported in C#; only in the CLR.
http://lookingsharp.wordpress.com/2010/03/08/tail-recursion-in-csharp-and-fsharp/[^]
The workaround looks interesting, but way too hardcore for the things the module is intended for. I will rarely need to loop, it's just to make sure it's flexible in case someone starts messing with the table while the site is live.
I wrote the first piece of code because I couldn't get it to work otherwise. It's pretty funny if it turns out to be better practice.
Giraffes are not real.
|
|
|
|
|
WHYYYYY??? If you're declaring Stuff in Page_Load and never doing anything with it, just nuke it all! Or did you not show the code that actually uses Stuff to populate the page or whatever?
|
|
|
|
|
Yes it's used for something of course. I'm not 'that' stupid.
Edit: and I'm not actually calling my variables "Stuff" either in case you're wondering.
Giraffes are not real.
|
|
|
|
|
0bx wrote: and I'm not actually calling my variables "Stuff" either
No? I'm disappointed. I found that rather original.
|
|
|
|
|
They're both horrors.
You don't ever need to return Stuff. Not to mention this "ShuffleNodeList" function is called each time loadStuff is called (I'm guessing it should only be called after everything has been loaded).
I wonder... is this code that is using the Umbraco API? Some of that looks familiar.
|
|
|
|
|
Yes it's the Umbraco api and it's not the complete code, it returns the list to be used in an other function that generates html in order to make the page look different every time you visit it.
Having the ShuffleNodeList was at the end at first... I though I had a good reason to put it in between at first, but looking at it doesn't make sense anymore.
Giraffes are not real.
|
|
|
|
|
0bx wrote: it returns the list to be used in an other function
But the calling function already has the list, as it was passed in as a parameter, so it does not need to be returned since it already exists at the location it would be returned to. I suppose returning it could make for shorter syntax, but not in the case you have shown.
|
|
|
|
|
I wonder, why u had to use recursion/goto at all:
protected void Page_Load(object sender, EventArgs e)
{
var Stuff = loadStuff();
}
private List<Node> loadStuff()
{
var Stuff = new List<Node>();
do
{
foreach (Node thing in Node.GetCurrent().Children)
{
Stuff.Add(thing);
}
Stuff = ShuffleNodeList(Stuff);
}
while (blablabla);
return Stuff;
}
|
|
|
|
|
On the no need for recursion and getting rid of the goto, can I add only doing a single shuffle:
protected void Page_Load(object sender, EventArgs e)
{
List<Node> Stuff = loadStuff();
}
private List<Node> loadStuff()
{
List<Node> Stuff = new List<Node>();
do {
foreach (Node thing in Node.GetCurrent().Children)
{
Stuff.Add(thing);
}
} while (Stuff.Count < 100 && Stuff.Count > 0))
return ShuffleNodeList(Stuff);
}
Nice, self contained and easy to follow.
Panic, Chaos, Destruction. My work here is done.
Drink. Get drunk. Fall over - P O'H
OK, I will win to day or my name isn't Ethel Crudacre! - DD Ethel Crudacre
I cannot live by bread alone. Bacon and ketchup are needed as well. - Trollslayer
Have a bit more patience with newbies. Of course some of them act dumb - they're often *students*, for heaven's sake - Terry Pratchett
|
|
|
|
|
Okay, I knew about the "While" loop, but I didn't know you can do it like this.
Giraffes are not real.
|
|
|
|
|
Chuckle! I think a lot of us do the same, when the occasion arises. I certainly do. Of course, there's no stigma involved in the practice, as long as you remember to test your replacement code thoroughly. Right? Right?
(As it happens, I also do it to my old, already-published fiction...which causes my readers a bit of concern when they discover it! Well, at least with fiction the "debugging" is less onerous.)
|
|
|
|
|
Gah! You needed that goto for the "Goto Hell" Achievement!
I remember when goto and gosub/return were the ONLY way to get around in your program flow, how times have changed!
|
|
|
|
|
|
0bx wrote: foreach (Node thing in Node.GetCurrent().Children)
{
Stuff.Add(thing);
}
Others have commented on the outer looping constructs. Regarding the inner foreach loop, I'd just get rid of it:
Stuff.AddRange(Node.GetCurrent().Children);
Cheers.
|
|
|
|