March 14, 2003
"Sean L. Palmer" <seanpalmer@directvinternet.com> wrote in message news:b4qkd6$12ms$1@digitaldaemon.com...
> Here's an idea:  Don't hire programmers that suck, or don't give them unlimited freedom to fuck up perfectly working code elsewhere in the codebase just because they "don't understand it".  Don't pull all the good programmers down just because there are bad programmers out there.
>
its not always the programmers, have a friend who did the oposite, striped out the junk and wrote a smart lazy evaluating fast version of some code, the manager then removed it all because he did not understand how it could work! turned out the manager wrote version 1 and was upset that some contractor could write in 1 month a perfectly working version of something the manager has spent a year bodging and bugfixing.

a good programmer is one who learns, and accepts there's always someone who can do (or has done) whatever better than they can (could). imho the best programmer is one how help the guy who can write a better version the code to do exactly that.

but I'm baised, I know I'm a shite programmer, but I still think " 'cos it is " is the worst reason for never explaining why something was implemented in a particular way and I'm lazy, why write something someone else has written and tested for you. (if it turns out it don't work you can blaim someone else and head off to the pub for the rest of the day.)

its bad project managment/leadership if someone who does not know what or why they are doing something is let loose on a section of code.

didn't some bloke 2000 years ago write "before you unwind the for loop in your brothers code take the unbounded recursion out of your own."




March 14, 2003
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> escreveu na mensagem news:3E70A041.E91A9210@deming-os.org...
> Thinking about my previous question, "Double Virtual...", and reading the links about multimethods, I ran across this idea:
>
> top_cast <expr>
>
> This would be a cast operator that, at runtime, discovers the actual (i.e. the top) type of the value, and casts it to that type.  Yes, that means that we are breaking the old C "know all types at compile time" paradigm.  However, there will only be a finite number of possible types that the <expr> could be cast to.  The compiler must attempt to compile code for each one.  However, some may be syntax errors (perhaps you pass the top_cast as a function parameter, but there is not a function implementation that takes all child classes).
>
> The interesting (and difficult) thing about this is that the compiler would have to compile different code paths, one for each possible top type, with an internal switch or lookup table.
>
> So, multimethods would be trivial to implement (from the programmer's
> perspective):
>
> class X;
> class C1 : X;
> class C2 : X;
>
> void foo(C1,C1);
> void foo(C1,C2);
> void foo(C2,C1);
> void foo(C2,C2);
>
> void foo(X a,X b)
> {
>     try {
>         foo(top_cast a, top_cast b);
>     }
>     catch(Error_top_cast_runtime_syntax_error)
>     {
>         printf("Oops!  I don't have a foo(...) function for these
> types!\n");
>     }
> }
>
> The function call here tells the compiler to, at runtime (or at compile time, if it can figure out enough stuff), determine what the top class of the variables "X a" and "X b" are.  It then calls the right method based on the type.
>
> I figure that the compiler could throw a Error_top_cast_runtime_syntax_error if it found at runtime a type (or, in this case, set of types) it could not handle.
>
> I expect that there are many other interesting possible uses for top_cast that I haven't considered yet, either...
>
> Thoughts?  Is the programming benefit worth the compiler complexity?
>     Russ
>
> --
> The Villagers are Online! http://villagersonline.com
>
> .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
> .[ (a version.of(English).(precise.more)) is(possible) ]
> ?[ you want.to(help(develop(it))) ]
>

This only works if there is always a most specialized method. But sometimes it's not the case:


class A;
class B : A;
class C : A;
class D : B;

void foo(A a, A b) {
    try {
        foo(top_cast a, top_cast b);
    } catch(Error_top_cast_runtime_syntax_error) {
        printf("Oops!  I don't have a foo(...) function for these
types!\n");
    }
}

foo(B,A)
foo(A,C)
foo(B,C)
foo(D,A)


What should we do when we call "foo(someD, someC)"? This problem can get worse with interfaces. This solution would be good just for some cases. I'm a big fan of multimethods, but they need language support to get right and safe. With this syntax there's also problems with return types: a method return void, another return int and other return Foo. But such feature could be defined as a library function, it just needs reflection to get right.


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.461 / Virus Database: 260 - Release Date: 10/3/2003


March 14, 2003
If you're trying to make a run-of-the-mill program, hire a run-of-the-mill programmer.  If you need something exotic, adding more lines of code won't necessarily get the problem solved.

I see your point.  If you don't need a guru, stay away from them;  they'll "upgrade" your codebase until mere mortals can't understand it.

Sean

"Bill Cox" <bill@viasic.com> wrote in message news:3E70E906.1000408@viasic.com...
>
> Hi, Sean.
>
> Sean L. Palmer wrote:
> > Here's an idea:  Don't hire programmers that suck, or don't give them unlimited freedom to fuck up perfectly working code elsewhere in the codebase just because they "don't understand it".  Don't pull all the
good
> > programmers down just because there are bad programmers out there.
> >
> > Sean
>
> What make a programmer a good programmer?  I'd say a good GUI programmer cranks out good GUIs fast.  A good Perl hacker generates HTML pages 10 times faster than most of the rest of us.  Good GUI programmers often don't understand how to write templates, never used unions, and really don't create very complex data structures.  Most Perl programmers don't use any of the high-level capabilities of Perl.
>
> I'd hire both of them.
>
> Bill


March 14, 2003
"Bill Cox" <bill@viasic.com> escreveu na mensagem news:3E70F283.1070301@viasic.com...
> Hi, again.  Just a few more random thoughts about hiring only good programmers...
>
> Sean L. Palmer wrote:
> > Here's an idea:  Don't hire programmers that suck, or don't give them unlimited freedom to fuck up perfectly working code elsewhere in the codebase just because they "don't understand it".  Don't pull all the
good
> > programmers down just because there are bad programmers out there.
> >
> > Sean
>
> I agree about keeping programmers who can mess up code away from the code.  I don't let our GUI guys hack our algorithms, and vise-versa. The main problem, though, isn't stupid programmers, it's inexperienced programmers.
>
> I look back at code I wrote a long time ago, and frankly, it stinks. Experience really does count, at least the first few years.  We hire mostly out of school, and always have a lot of training to do.  I'd say we succeed in hiring very bright people, and that it pays off to do so, even if we have to train them.  However, we have to help them get through that phase when their code still stinks.
>
> Naturally, every bright programmer we hire wants to jump right in and work on the most sensitive code.  It's hard to hold them back to simpler, well contained pieces of the system while they're still learning.  A lot of the problems arise when I relent, and put a guy into a situation he's not quite ready for.  A lot of the problems are therefore really my fault.
>
> However, there's another nasty condition that I run into.  The smarter a guy is, the more he hates reading other peoples code.  They practically look for excuses to rewrite it (BTW, I do let them rewrite tons of code... old code can be a liability).  This results in good code being deleted and re-written badly pretty often.  Also, when a smart guy gets an idea, it's often really hard to change it, even when he's wrong.  I'd say posts on this group support this assertion.  I'm not goint to claim to be an exception.
>
> Here's a receient example at work.  I hired a brilliant guy out of Duke, and have been training him for two years.  He's scary smart.  For example, there were several years where he never got a math problem wrong on any test, including SAT, SAT2, AP tests, and several high-school and college classes.  I've found that these kinds of guys make great algorithms developers, and he's worked out well overall.
>
> He hates the fact that we have duplicated a very complex function in the routing database in two different places.  It's morally offensive to him.  The same code is literally repeated, but with minor changes.  The first version computes the shape of a wire from the routing data structures.  The second computes what shape would result if we built the routing data structures, but does it without building them.  The direct computation from the data structures is the most inner-loop code in our system.  The what-if code runs several times slower.
>
> I updated my source code a couple weeks ago, and all my stuff ran much slower.  I wasted half the day to find that he'd deleted (not commented out) the fast direct computation, and emulated it's functionality by calling the what-if version.  I had to check out an old version and undo his hack, but I also added a capability so that in debug mode, the what-if version is called, and the results are compared to the normal version.  We still have two similar copies of code, but at least we know they are in sync.
>
> I updated again a couple of days ago, and the slow behavior came back. It turns out he'd commented out the if-statement around the check, so that it was always called.  Of course, I had to put it back the way it was, so our tools would run at a competitive speed, and so I could get my work done in reasonable time.  I bet that the slow behavior will be back next time I update.
>
> What do you do?  The smartest programmers are often the ones causing the most problems.  I can't fire them.  They're too productive.  In fact, they know it, and do all kinds of crap just to piss you off!  It's just part of living in the real world.  And besides, I deserve it.  My old bosses tell horror stories about having to manage me.
>
> Bill
>

Here's my two cents. Since I started studying project management (and working as a consultant in these techniques) there's one thing about teams that I never ignore. You have to be able to trust in your team. If they lie to you, they work behind the scenes, they have their own agenda or if they have no concept of responsibility, things will just get worse over time. Good programmers can write efficient and well-designed software, not only one of these. It's a matter of time for a bad programmer to mess with an entire project. You can define some rules, like minimum performance, and write automated tests to check this. Run these tests every other hour, before every build, whenever you'll think it's important, and treat their failures as bugs. Make these programmers know that if performance goes down it's a bug and they should never put bugs in. At least you'll be able to verify when things get wrong.


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.461 / Virus Database: 260 - Release Date: 10/3/2003


March 14, 2003
Daniel Yokomiso wrote:

> This only works if there is always a most specialized method. But sometimes it's not the case:
>
> class A;
> class B : A;
> class C : A;
> class D : B;
>
> void foo(A a, A b) {
>     try {
>         foo(top_cast a, top_cast b);
>     } catch(Error_top_cast_runtime_syntax_error) {
>         printf("Oops!  I don't have a foo(...) function for these
> types!\n");
>     }
> }
>
> foo(B,A)
> foo(A,C)
> foo(B,C)
> foo(D,A)
>
> What should we do when we call "foo(someD, someC)"? This problem can get worse with interfaces. This solution would be good just for some cases. I'm a big fan of multimethods, but they need language support to get right and safe. With this syntax there's also problems with return types: a method return void, another return int and other return Foo. But such feature could be defined as a library function, it just needs reflection to get right.

The runtime algorithm would be as follows:

1) Cast all top_cast expressions to their current (top) type.  This is NOT
ambiguous, since each reference points to a single object, and all objects have
a single type, even though you have many possible pointers.
2) Evaluate the expression as though the programmer had manually cast these
expressions to these types.  Likewise, this is NOT ambiguous, because D has
resolution rules.
3) If there is no legal way to evaluate the runtime type combination, then throw
Error_top_cast_runtime_syntax_error

Please, though, restate your example.  I didn't understand it entirely.  What overloaded versions of foo() are available?

Also note that your example can potentially do infinite recursion if foo(A,A) calls itself because the objects are both literal A objects (or if that is the best implementation for the combination of objects that you pass it).

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


March 14, 2003
> Here's my two cents. Since I started studying project management (and
> working as a consultant in these techniques) there's one thing about teams
> that I never ignore. You have to be able to trust in your team.

I agree.  I may have given the impression that I manage my teams. That's not exactly right.  I fill a lead technical roll, and try to get a good manager involved to run the group.  It's a tag-team aproach that I've found extremely effective.  There are huge benifits in having the group's technical lead/mentor not be everyone's boss.

I haven't studied management techniques at all, but I've found it odd that this tag-team aproach isn't more wide spread.  Usually, companies promote the best tech guy, often losing a great asset while creating a monster.

Bill

March 14, 2003

Mike Wynn wrote:
> "Sean L. Palmer" <seanpalmer@directvinternet.com> wrote in message
> news:b4qkd6$12ms$1@digitaldaemon.com...
> 
>>Here's an idea:  Don't hire programmers that suck, or don't give them
>>unlimited freedom to fuck up perfectly working code elsewhere in the
>>codebase just because they "don't understand it".  Don't pull all the good
>>programmers down just because there are bad programmers out there.
>>
> 
> its not always the programmers, have a friend who did the oposite, striped
> out the junk and wrote a smart lazy evaluating fast version of some code,
> the manager then removed it all because he did not understand how it could
> work! turned out the manager wrote version 1 and was upset that some
> contractor could write in 1 month a perfectly working version of something
> the manager has spent a year bodging and bugfixing  Just another story along these lines...

At QuickLogic, I read a paper called RICE, which was a fun mathematical way to quickly predict net delays in circuits.  I wrote a prototype over the weekend, and demonstrated it Monday.  The code worked great.  It dramatically improved our timing estimates, giving good estimates 99.99% of the time (the other .01% had to be done with the old techniques).

My boss at the time was my EDA mentor, a truly brilliant guy and outstanding programmer, but with no background in math.  He couldn't understand how my code worked, so he simply refused to believe it.  He wouldn't let me put it in the tools until he had it validated.

He hired Professor Pillage to come examine my work.  Professor Pillage was the author of the RICE paper.  It turns out that RICE failed to get a good answer 10% of the time, not 0.01% like my version.  I showed him how to fix RICE.  Then, he went around to all the EDA companies, and showed them how to do it!  It remains the standard aproach today.

BTW, back around 1994, I upgraded QuickLogic's timing estimation to a better method, which makes AWE obsolete for net delay estimation.  I tried to publish it, but the academics wouldn't accept it without a professor behind it!  If you're interested, I've got a weak patent on the topic that explains how to do it, and is easy to work around: 5,675,502.

Bill

March 15, 2003
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> escreveu na mensagem news:3E71DB70.485FEC81@deming-os.org...
> Daniel Yokomiso wrote:
>
> > This only works if there is always a most specialized method. But
sometimes
> > it's not the case:
> >
> > class A;
> > class B : A;
> > class C : A;
> > class D : B;
> >
> > void foo(A a, A b) {
> >     try {
> >         foo(top_cast a, top_cast b);
> >     } catch(Error_top_cast_runtime_syntax_error) {
> >         printf("Oops!  I don't have a foo(...) function for these
> > types!\n");
> >     }
> > }
> >
> > foo(B,A)
> > foo(A,C)
> > foo(B,C)
> > foo(D,A)
> >
> > What should we do when we call "foo(someD, someC)"? This problem can get worse with interfaces. This solution would be good just for some cases.
I'm
> > a big fan of multimethods, but they need language support to get right
and
> > safe. With this syntax there's also problems with return types: a method return void, another return int and other return Foo. But such feature
could
> > be defined as a library function, it just needs reflection to get right.
>
> The runtime algorithm would be as follows:
>
> 1) Cast all top_cast expressions to their current (top) type.  This is NOT
> ambiguous, since each reference points to a single object, and all objects
have
> a single type, even though you have many possible pointers.
> 2) Evaluate the expression as though the programmer had manually cast
these
> expressions to these types.  Likewise, this is NOT ambiguous, because D
has
> resolution rules.
> 3) If there is no legal way to evaluate the runtime type combination, then
throw
> Error_top_cast_runtime_syntax_error
>
> Please, though, restate your example.  I didn't understand it entirely.
What
> overloaded versions of foo() are available?
>
> Also note that your example can potentially do infinite recursion if
foo(A,A)
> calls itself because the objects are both literal A objects (or if that is
the
> best implementation for the combination of objects that you pass it).
>
> --
> The Villagers are Online! http://villagersonline.com
>
> .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
> .[ (a version.of(English).(precise.more)) is(possible) ]
> ?[ you want.to(help(develop(it))) ]


    This is a simple program tested with dmd 0.59.


class A {
}
class B : A {
}
class C : A {
}
class D : B {
}

void foo(A a1, A a2) {
    printf("foo(A,A)\r\n");
}
void foo(B b, A a) {
    printf("foo(B,A)\r\n");
}
void foo(A a, C c) {
    printf("foo(A,C)\r\n");
}
void foo(B b, C c) {
    printf("foo(B,C)\r\n");
}
void foo(D d, A a) {
    printf("foo(D,A)\r\n");
}
1int main() {
   A a = new A();
   B b = new B();
   C c = new C();
   D d = new D();
   foo(a, a); // foo(A,A)
   foo(a, b); // foo(A,A)
   foo(a, c); // foo(A,C)
   foo(a, d); // foo(A,A)
   foo(b, a); // foo(B,A)
// function foo overloads void(A a1,A a2) and void(B b,A a) both match
argument list for foo
//   foo(b, b);
   foo(b, c); // foo(B,C)
// function foo overloads void(A a1,A a2) and void(B b,A a) both match
argument list for foo
//   foo(b, d);
   foo(c, a); // foo(A,A)
   foo(c, b); // foo(A,A)
// function foo overloads void(A a1,A a2) and void(A a,C c) both match
argument list for foo
//   foo(c, c);
   foo(c, d); // foo(A,A)
   foo(d, a); // foo(D,A)
// function foo overloads void(A a1,A a2) and void(D d,A a) both match
argument list for foo
//   foo(d, b);
// function foo overloads void(A a1,A a2) and void(D d,A a) both match
argument list for foo
//   foo(d, c);
// function foo overloads void(A a1,A a2) and void(D d,A a) both match
argument list for foo
//   foo(d, d);

   return 0;
}


    It's difficult to define what is the most specialized version of the
method. There's a long list of discussions about it in Usenet. I
participated in some discussions in comp.lang.eiffel. There's also a problem
if you define a function overloaded for interfaces:


interface I {
}
interface J {
}
void foo(I i, J j) {
    printf("foo(I,J)\r\n");
}
void foo(J j, I i) {
    printf("foo(J,I)\r\n");
}
class A : I {
}
class B : J {
}
class C : I, J {
}

int main() {
    A a  = new A();
    B b  = new B();
    C c = new C();
    I i = a;
    J j = b;
    I ic = c;
    J jc = c;

    foo(a, b); // foo(I,J)
    foo(b, a); // foo(J,I)

    foo(a, c); // foo(I,J)
    foo(b, c); // foo(J,I)
// function foo overloads void(I i,J j) and void(J j,I i) both match
argument list for foo
//    foo(c, c);
    foo(c, a); // foo(J,I)
    foo(c, b); // foo(I,J)

    foo(i, j); // foo(I,J)
    foo(j, i); // foo(J,I)

    foo(i, jc); // foo(I,J)
    foo(ic, j); // foo(I,J)


    return 0;
}


    I can write more examples showing how different combinations of method
definitions and calls can be resolved in a static context, but may fail in
runtime, while some other combinations could work in a runtime context, but
fail in static time. If you add OO polymorphism things get worse, because
any possible descendent can write additional methods that'll cause ambiguity
at runtime. To provide multi-dispatch we need compiler support to invalidate
ambiguous cases and force the programmer to disambiguate them (by adding
more function versions).



---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.461 / Virus Database: 260 - Release Date: 10/3/2003


March 15, 2003
Daniel Yokomiso wrote:

> It's difficult to define what is the most specialized version of the method. There's a long list of discussions about it in Usenet. I participated in some discussions in comp.lang.eiffel. There's also a problem if you define a function overloaded for interfaces:

Fair enough.  But the problem is already confronted in D, as you point out.  The issue is orthogonal to top_cast.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


March 15, 2003
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> escreveu na mensagem news:3E72D829.67D10122@deming-os.org...
> Daniel Yokomiso wrote:
>
> > It's difficult to define what is the most specialized version of the method. There's a long list of discussions about it in Usenet. I participated in some discussions in comp.lang.eiffel. There's also a
problem
> > if you define a function overloaded for interfaces:
>
> Fair enough.  But the problem is already confronted in D, as you point
out.  The
> issue is orthogonal to top_cast.
>
> --
> The Villagers are Online! http://villagersonline.com
>
> .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
> .[ (a version.of(English).(precise.more)) is(possible) ]
> ?[ you want.to(help(develop(it))) ]

Such feature (top_cast) needs specialized support to work correctly or it can introduce weird bugs in your application. In cases like this (double-dispatch) the standard OO solution is a visitor or something similar. There's a nice link at wiki, with lots of discussion on the related pages.


http://c2.com/cgi/wiki?DoubleDispatchExample


In D we can have a multidispatch solution using delegates, as in Burton's post. These two solutions are safe and easy to predict.



---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.462 / Virus Database: 261 - Release Date: 13/3/2003