www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Make code that is wrong, look wrong...

reply "Regan Heath" <regan netwin.co.nz> writes:
http://joelonsoftware.com/articles/Wrong.html
An article by "Joel Spolsky".
I loved it.

Regan
May 31 2005
next sibling parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
Regan Heath wrote:
 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.
 
 Regan

Well, I read about half of it .. until he explained his method. quote: The Real Solution So let me suggest a coding convention that works. We’ll have just one rule: All strings that come from the user must be stored in variables (or database columns) with a name starting with the prefix "us" (for Unsafe String). All strings that have been HTML encoded or which came from a known-safe location must be stored in variables with a name starting with the prefix "s" (for Safe string). /quote I disagree .. that's a weak solution. You simply can't guarantee that there will be no line of code with this "bug". You can only see it when skimming through, but you probably won't skim through every single file in your huge project. The real solution is to design the structure of the program in a way such that the error can be prevented. OOP is probably a better solution. DataBaseEntries are objects, Strings are objects. encapsulate strings in an object, and encapsulate user input source in an object .. You can define a sort of DefensiveHTMLString, and a user input object, and an input source. then to recieve stuff from the user, use: DefensiveString s = inputSource.Request("Hello"); here, the input source will flag the string inputted by the user as "unsafe" before assigning it to s. It's flaged as unsafe because it came from the user. Now, to actually retrive what's in the string, page.Write(s.getString()); getString() will return an encoded version, because "s" is unsafe. To store it in a DB, you would use a DBEntry bject, and set its content to 's'. In D or java, this would probably require the use of interfaces. With a similar (and better) kind of structure, you don't need to worry about spotting the bug, because the liklihood of it occuring is eliminated (read: drastically reduced). What is better? Elliminating the source of the bug, or finding ways to help you debug your poorly designed code? Gotta love OOP!! :) Actually, in a pure(r) oop, you wouldn't /flag/ the object 's' as "unsafe", you would simply instantiate it as an instance of UnsafeString, which would be a subclass of DefensiveString ... or something like that.
May 31 2005
prev sibling next sibling parent reply =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Regan Heath wrote:

 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.

I didn't. :-) Hungarian got a bad name by Microsoft's use of it, and is really a nice guy ? (despite his appearance) Exceptions and gotos are both bad, and error codes are much better. And all the extra idents makes it easier? They both remove me from the Quality Plateau, and distract. If it works for you, then follow it. Maybe we're different? --andres
Jun 01 2005
next sibling parent reply Brad Beveridge <brad somewhere.net> writes:
Anders F Björklund wrote:
 Regan Heath wrote:

 Exceptions and gotos are both bad, and error codes are
 much better. And all the extra idents makes it easier?

I don't use exceptions much, so this was a new bit of info for me. Exceptions, especially lower down the call chain, can break the usual flow of code execution (hence, exception :)). How do people normally go about making their code more exception tolerant? The obvious answer is to catch exceptions as close to the offending problem as possbile. But what if you forget to catch an exception? If I were going through the process of making my code more robust, how can I test that I am catching exceptions in the correct place? It sounds like the best place for this kind of checking is a tool that statically analyses the code and produces some sort of graph that shows where exceptions can possibly propagate to. Is this something that will fit into the DMD front end code? Cheers Brad
Jun 01 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <d7kpq2$24j8$1 digitaldaemon.com>, Brad Beveridge says...
How do people normally go about making their code more exception 
tolerant?  The obvious answer is to catch exceptions as close to the 
offending problem as possbile.  But what if you forget to catch an 
exception?

In C++, RAII is the agreed upon way to create exception-safe code. In D, it would look something like this: # void func( Transaction t ) # { # auto class Rollback # { # this( Transaction t ) { m_tran = tran; } # ~this() { if( m_tran ) m_tran.rollback(); } # # void disable() { m_tran = null; } # private Transaction m_tran; # } # # auto Rollback rb = new Rollback( t ); # # // do stuff with t # # // since everything was successful # // (because execution got this far) # // do not rollback this transaction # rb.disable(); # } Here, the transaction will be automatically rolled back if the function exits prematurely. Better C++ APIs will typically offer such classes for common operations. For example, a C++ threading library I've written contains a ScopedLock class to ensure that Mutexes are released automatically on scope exit. Things like this can be invaluable in preventing bugs not only in initial code design but in long-term maintenance as well. For the record, "RAII" stands for "Resource Acquisition Is Initialization." Sean
Jun 01 2005
parent Brad Beveridge <brad somewhere.net> writes:
Sean Kelly wrote:

 Here, the transaction will be automatically rolled back if the function exits
 prematurely.  Better C++ APIs will typically offer such classes for common
 operations.  For example, a C++ threading library I've written contains a
 ScopedLock class to ensure that Mutexes are released automatically on scope
 exit.  Things like this can be invaluable in preventing bugs not only in
initial
 code design but in long-term maintenance as well.
 

dope when it comes to OO, writing system drivers in C is my day job - OO & D are just a hobby :) I guess that my concern (after reading the Joel column) with exceptions is that say I have this kind of call structure A() calls B() calls C() C() throws two types of exceptions, the ReallyCommonException and the UnCommonException. B() catches the ReallyCommonException, because it is well documented and B() knows how to continue on. Infact, B() thinks that it will properly catch ALL exceptions - but B() is wrong. A() expects to always get a result out of B(), and A() doesn't expect any exception to get past B(). I guess my concern is that A() expects B() to always sheild it from exceptions. B() expects to only catch the documented (say we have a 3rd party library) exception. C() is obviously the bad apple here - but A() or B() need to deal with it. I guess what I am saying is : Assuming that you have a binary only library, with incorrect documentation - it would be nice to find out which exceptions each function throws, so that you can be sure you are catching them all. As I said earlier - I just dabble with this stuff & only rarely use Exceptions anyhow, so maybe what I am saying is just plain wrong. Cheers Brad
Jun 01 2005
prev sibling next sibling parent Ilya Minkov <minkov cs.tum.edu> writes:
Anders F Björklund schrieb:
 I didn't. :-)
 
 Hungarian got a bad name by Microsoft's use of it, and is really a
 nice guy ? (despite his appearance)

He might have a point - sort of - though, as has been said often enough, hungarian is pre-C++. In a typesafe language one would just declare his own type, say, QuotedString, and only allow that to be printed into the document. Anyway, a single example is only enough to dismiss, not to prove an point.
 Exceptions and gotos are both bad, and error codes are much better.
 And all the extra idents makes it easier?

Oh, yes, and the most evil of all: continue and break. :) Oh, and while we're at it: let's declare switch/case evil since it uses break so often. :))) And premature ... [optimization? no! ej...? no!] ... RETURN is a rppt pf sll 3v1L !!!
 They both remove me from the Quality Plateau, and distract. If it
 works for you, then follow it. Maybe we're different?

Software is complex today. What is appropriate if a simple program fails? Do as if it succeeded? No! Rather bailout quickly and with an error state. Exceptions are just that - they allow one to kill a sub-program - particularly a part of an execution stack - up until a higher-level, independant part of the program may discard that, perhaps inform a user, and continue working. If a failure has occured, i don't want that piece of code running any longer, tampering further with some resource which has caused the failure. And that's what exceptions are truly wonderful for. A code requiered to check global error state or return values would often fail to do that correctly. Probably good and correct exception-handling code is just as rare, but at least IT RETURNS the control RELIABLY to the main program. -eye
Jun 02 2005
prev sibling parent reply "Jim H" <jhewesNOSPAM ix.netcom.com> writes:
"Anders F Björklund" <afb algonet.se> wrote in message 
news:d7joto$tj1$1 digitaldaemon.com...
 Exceptions and gotos are both bad, and error codes are
 much better. And all the extra idents makes it easier?

Spolsky and Chen do seem to dislike exceptions. When I first found the D site, this sentence in the Overview popped out at me in particular: "Exception handling. More and more experience with exception handling shows it to be a superior way to handle errors than the C traditional method of using error codes and errno globals. " I've never known conclusively whether exception handling is a good thing or not. You can search on newsgroups for plenty of discussions and debates on it, and I've done that. But what you usually see are people arguing both sides of the debate. Given that quote above, is there some argument or evidence that anyone can point me to that would convince me one way or the other? I don't mean to start a debate right here; rather I'm asking more for references. People will usually say "exceptions should be used for exceptional circumstances." Unfortunately this tells me nothing unless you define what an exceptional circumstance is. In some cases I think it can even be up to the calling function, not the callee, as to what is exceptional or not. So I'd like to hear a better explanation than that. Jim
Jun 04 2005
next sibling parent Trevor Parscal <trevorparscal hotmail.com> writes:
I use exception handling when I don't trust the function I am calling.

Thats the only time I use them personally.

-- 
Thanks,
Trevor Parscal
www.trevorparscal.com
trevorparscal hotmail.com
Jun 04 2005
prev sibling next sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Jim H wrote:

Exceptions and gotos are both bad, and error codes are
much better. And all the extra idents makes it easier?

Spolsky and Chen do seem to dislike exceptions.

Yes, and I probably should have written that better since it's been quoted a few times now: it wasn't *my* opinions. I'm using either exceptions or gotos, and liking it...
 "Exception handling. More and more experience with exception handling shows 
 it to be a superior way to handle errors than the C traditional method of 
 using error codes and errno globals. "

 Given that quote above, is there some argument or evidence that anyone can 
 point me to that would convince me one way or the other? I don't mean to 
 start a debate right here; rather I'm asking more for references.

I'm not sure about others, but I'm updating C code that looks like: foo = calloc(1,sizeof(*foo)); if (!foo) return NULL; bar = calloc(1,sizeof(*bar)); if (!bar) { free(foo); return NULL; } baz = calloc(1,sizeof(*baz)); if (!baz) { free(foo); free(bar); return NULL; } foo->bar = bar; foo->baz = baz; return foo; Having exceptions (and garbage collection) would surely have helped ? The file reading code would similarly benefit, too long for an example. Writing the above code "Pascal-style", with indented ifs and a single point of return at the bottom only makes it worse (in my own opinion). But unless I'm horribly mistaken, that's the approach they advocated ? (in http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx) --anders
Jun 05 2005
parent "Jim H" <jimh nowhere.com> writes:
"Anders F Björklund" <afb algonet.se> wrote in message 
news:d7uknk$199j$1 digitaldaemon.com...
 Jim H wrote:

Exceptions and gotos are both bad, and error codes are
much better. And all the extra idents makes it easier?

Spolsky and Chen do seem to dislike exceptions.

Yes, and I probably should have written that better since it's been quoted a few times now: it wasn't *my* opinions.

Oh, I understood what you meant---that you were sort of quoting them. I was just agreeing with you. Jim
Jun 07 2005
prev sibling parent Ilya Minkov <minkov cs.tum.edu> writes:
Jim H schrieb:
 Given that quote above, is there some argument or evidence that 
 anyone can point me to that would convince me one way or the other? I
  don't mean to start a debate right here; rather I'm asking more for 
 references.

It somehow seems to me that my point has gone down in the deep bath of sarcasm. One can have long debates on whether the locality of code (return value checking), or separation between action and error handling (exceptions, errorcodes) is the right way, and whether the traditional or exception-based error-handling is easier to write or more or less errorprone and whatnot, but there are some things which are somewhat less disputable. 1. Traditional error handling - either of them - can make your program in a faulty state running in rounds, stepping more and more often on the aching toe. And there's not much you can do to notice it beforehand. Exception handling, on the other hand, terminates the execution of the faulty branch rapidly, and gives control to a higher level of the calling stack, which claims to be able to handle that. If done once correctly at the top level, i have the experience that it can hold a complex system running. There is not much you can do wrong in the rest of the code, except for one highly dangerous thing: NEVER allow a destructor to throw. 2. Exception Handling has somewhat spoiled its appearence in the eyes of many programmers by being used for example in Java for Input/Output and other operations which are highly likely to fail, and where you might get a soup of exception handlers, and this situation was strongly amplified by introducing checked exceptions. Many programmers find the net result less than appealing, though i wouldn't like to take a position in this discussion. I would just like to state that D doesn't enforce strong exception checking, nor does it force exceptions for Input/Output (though it mandates them - the standard library uses them), so i think this is something more programmers would be able to live with, eventually seeng that exceptions are, well, quite usable too. I am very lazy writing error handling code, so for me, exceptions have been a wonderful thing. I only define a few spots where i can discard everything that happened down the execution stack and give error, or retry, or something.
 People will usually say "exceptions should be used for exceptional 
 circumstances." Unfortunately this tells me nothing unless you define
  what an exceptional circumstance is. In some cases I think it can 
 even be up to the calling function, not the callee, as to what is 
 exceptional or not. So I'd like to hear a better explanation than 
 that.

If you think that something is not exceptional - that is, you expect that - you just catch the exception thrown by the function below, otherwise leave as is. In the case you catch, it is not very different from error codes - you must somehow decide what to do. It's the other case that is different - with traditional error handling, the code keeps running. You should be aware, that if a sequence of operations is somehow interdependant, the next ones will usually fail as well. I don't think there is much dispute on the side of the callee whether it should throw or not. A function has a specification, and in the case that it cannot be fulfilled due to some runtime circumstance, it throws an exception. If throwing becomes way too usual, one should consider defining a new function differently. While deciding on the specification, it is probably helpful to consider that a programmer might find a function with a simpler specification more appealing to use. I believe, for example, Phobos to be quite a success in this respect. -eye
Jun 05 2005
prev sibling next sibling parent reply David Medlock <noone nowhere.com> writes:
Regan Heath wrote:
 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.
 
 Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM
Jun 01 2005
parent reply Brad Beveridge <brad somewhere.net> writes:
David Medlock wrote:
 Regan Heath wrote:
 
 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.

 Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM

D has strict typedefs so you can create new types, which the compiler will complain about. Ie, from his row/col example typedef int rowType; typedef int colType; rowType r; colType t; r = t; // D compiler will catch this. So, if you want to write truely robust code you can create a slew of new types to ensure that any conversion from type to type will not be implicit. Brad
Jun 01 2005
next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Brad Beveridge wrote:
 David Medlock wrote:
 
 Regan Heath wrote:

 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.

 Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM

Really, what it boils down to is "give your variables sensible names". D has strict typedefs so you can create new types, which the compiler will complain about. Ie, from his row/col example typedef int rowType; typedef int colType; rowType r; colType t; r = t; // D compiler will catch this. So, if you want to write truely robust code you can create a slew of new types to ensure that any conversion from type to type will not be implicit. Brad

Indeed, I think you only need something like hungarian notation is when you don't have strong types. safe and unsafe strings should have different types, and the function that is used to retrive user input, should return it as an unsafe string. This way, you wouldn't need to prefix variable names.
Jun 01 2005
next sibling parent "Kris" <fu bar.com> writes:
"Hasan Aljudy" <hasan.aljudy gmail.com> wrote in message
news:d7l6oo$2gtm$1 digitaldaemon.com...
 Brad Beveridge wrote:
 David Medlock wrote:

 Regan Heath wrote:

 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.

 Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM

Really, what it boils down to is "give your variables sensible names". D has strict typedefs so you can create new types, which the compiler will complain about. Ie, from his row/col example typedef int rowType; typedef int colType; rowType r; colType t; r = t; // D compiler will catch this. So, if you want to write truely robust code you can create a slew of new types to ensure that any conversion from type to type will not be


 Brad

Indeed, I think you only need something like hungarian notation is when you don't have strong types. safe and unsafe strings should have different types, and the function that is used to retrive user input, should return it as an unsafe string. This way, you wouldn't need to prefix variable names.

Part of the problem here is that some people (in MS, as I understand it) would write function bodies of prodigeous and alarming proportion (CS was one). Given that, it was nigh impossible to eyball the code and locate data types. This behaviour should have disappeared with GWBasic, but not for some folks. Regardless of the type-system or design approach used (including OOP), concise bodies of code can help tremendously. There are always exceptions though, and YMMV. Without intending to offend anyone's sensibilities, I feel Spolsky's article is targeting those who have little or no concept of structured coding. Further; while he identifies behaviour such as "cleaning house" and refactoring as being forerunners to full-blown AppHungarian syndrome, I feel that's a different attribute altogether. I mean, Ben is discussing doing the same thing with Phobos right now ~ I don't think he's about to suggest introducing Hungarian to D ~ are you, Ben? But the history of contorted-evolution was interesting :-)
Jun 01 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 01 Jun 2005 14:45:19 -0600, Hasan Aljudy wrote:

 Brad Beveridge wrote:
 David Medlock wrote:
 
 Regan Heath wrote:

 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.

 Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM

Really, what it boils down to is "give your variables sensible names". D has strict typedefs so you can create new types, which the compiler will complain about. Ie, from his row/col example typedef int rowType; typedef int colType; rowType r; colType t; r = t; // D compiler will catch this. So, if you want to write truely robust code you can create a slew of new types to ensure that any conversion from type to type will not be implicit. Brad

Indeed, I think you only need something like hungarian notation is when you don't have strong types. safe and unsafe strings should have different types, and the function that is used to retrive user input, should return it as an unsafe string. This way, you wouldn't need to prefix variable names.

I agree that a good type system caters for previous uses of Hungarian notation. However, I use prefixes on variable names to indicate scope. This serves the same premise that the author was promoting, namely that a person doesn't have to read a lot of code far from the current line to gain useful information about the variable. Examples: pText ~~ 'p' indicates that this is a parameter passed to the function. lScale ~~ 'l' indicates that this is scoped to the function or block. vHigh ~~ 'v' indicates it is scoped to the module gRow ~~ 'g' indicates it is globally scoped ie 'public' mStyle ~~ 'm' indicates it is scoped to the class 'private' -- Derek Parnell Melbourne, Australia 2/06/2005 7:24:50 AM
Jun 01 2005
next sibling parent Sean Kelly <sean f4.ca> writes:
In article <sfj3zr1o3hx8.1q4wcqi7mqbsl.dlg 40tude.net>, Derek Parnell says...
I agree that a good type system caters for previous uses of Hungarian
notation. However, I use prefixes on variable names to indicate scope. 
This serves the same premise that the author was promoting, namely that a
person doesn't have to read a lot of code far from the current line to gain
useful information about the variable.

Examples:
 pText  ~~ 'p' indicates that this is a parameter passed to the function.
 lScale ~~ 'l' indicates that this is scoped to the function or block.
 vHigh  ~~ 'v' indicates it is scoped to the module
 gRow   ~~ 'g' indicates it is globally scoped ie 'public'
 mStyle ~~ 'm' indicates it is scoped to the class 'private'

Agreed. Personally, I use a simplified version of the above: m_var1 ~~ 'm_' indicates this is a non-public member variable sm_var2 ~~ 'sm_' indicates this is a non-public static member variable And that's it. For most of the rest I typically use namespaces in C++, so I suppose I'd use structs or some such in D. Sean
Jun 01 2005
prev sibling parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
Derek Parnell wrote:
 On Wed, 01 Jun 2005 14:45:19 -0600, Hasan Aljudy wrote:
 
 
Brad Beveridge wrote:

David Medlock wrote:


Regan Heath wrote:


http://joelonsoftware.com/articles/Wrong.html
An article by "Joel Spolsky".
I loved it.

Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM

Really, what it boils down to is "give your variables sensible names". D has strict typedefs so you can create new types, which the compiler will complain about. Ie, from his row/col example typedef int rowType; typedef int colType; rowType r; colType t; r = t; // D compiler will catch this. So, if you want to write truely robust code you can create a slew of new types to ensure that any conversion from type to type will not be implicit. Brad

Indeed, I think you only need something like hungarian notation is when you don't have strong types. safe and unsafe strings should have different types, and the function that is used to retrive user input, should return it as an unsafe string. This way, you wouldn't need to prefix variable names.

I agree that a good type system caters for previous uses of Hungarian notation. However, I use prefixes on variable names to indicate scope. This serves the same premise that the author was promoting, namely that a person doesn't have to read a lot of code far from the current line to gain useful information about the variable. Examples: pText ~~ 'p' indicates that this is a parameter passed to the function. lScale ~~ 'l' indicates that this is scoped to the function or block. vHigh ~~ 'v' indicates it is scoped to the module gRow ~~ 'g' indicates it is globally scoped ie 'public' mStyle ~~ 'm' indicates it is scoped to the class 'private'

I sometimes prefix function parameters with p, specially when the name conflicts with a local name (or a member variable, if the function is a member function). Type prefixes can server for easier readability sometimes, but I don't think it's really a good idea to use them for the purpose of "spotting bugs in my poorly structured code".
Jun 01 2005
prev sibling next sibling parent reply David Medlock <noone nowhere.com> writes:
Brad Beveridge wrote:
 David Medlock wrote:
 
 Regan Heath wrote:

 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.

 Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM

Really, what it boils down to is "give your variables sensible names". D has strict typedefs so you can create new types, which the compiler will complain about. Ie, from his row/col example typedef int rowType; typedef int colType; rowType r; colType t; r = t; // D compiler will catch this. So, if you want to write truely robust code you can create a slew of new types to ensure that any conversion from type to type will not be implicit. Brad

Yes, but his point(and Raymond Chen's) is that you do not prefix based on *scope* or *type* but usage. I think this is more powerful than the others. Really does it matter that a x coordinate is an int, or that is is a class or module variable? No, just that it represents screen coordinates. -DavidM
Jun 01 2005
parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
David Medlock wrote:
 Brad Beveridge wrote:
 
 David Medlock wrote:

 Regan Heath wrote:

 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.

 Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM

Really, what it boils down to is "give your variables sensible names". D has strict typedefs so you can create new types, which the compiler will complain about. Ie, from his row/col example typedef int rowType; typedef int colType; rowType r; colType t; r = t; // D compiler will catch this. So, if you want to write truely robust code you can create a slew of new types to ensure that any conversion from type to type will not be implicit. Brad

Yes, but his point(and Raymond Chen's) is that you do not prefix based on *scope* or *type* but usage. I think this is more powerful than the others. Really does it matter that a x coordinate is an int, or that is is a class or module variable? No, just that it represents screen coordinates. -DavidM

By variable usage, you mean "what it represents"? well, for me, that's a type (read: class). What's the difference between struct vector { int x; int y; } and struct dimension { int width; int height; } there is no physical difference, but a conceptual one. Off of my head, I'm guessing Joel Spolsky would use COORD to represent both, then prefix variable with vec- dim- Is that "usage" or "type"? I don't think there is a practical difference. Different (or special) usage implies a new type to me.
Jun 01 2005
parent reply David Medlock <noone nowhere.com> writes:
Hasan Aljudy wrote:
 David Medlock wrote:
 
 Brad Beveridge wrote:

 David Medlock wrote:

 Regan Heath wrote:

 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.

 Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM

Really, what it boils down to is "give your variables sensible names". D has strict typedefs so you can create new types, which the compiler will complain about. Ie, from his row/col example typedef int rowType; typedef int colType; rowType r; colType t; r = t; // D compiler will catch this. So, if you want to write truely robust code you can create a slew of new types to ensure that any conversion from type to type will not be implicit. Brad

Yes, but his point(and Raymond Chen's) is that you do not prefix based on *scope* or *type* but usage. I think this is more powerful than the others. Really does it matter that a x coordinate is an int, or that is is a class or module variable? No, just that it represents screen coordinates. -DavidM

By variable usage, you mean "what it represents"? well, for me, that's a type (read: class). What's the difference between struct vector { int x; int y; } and struct dimension { int width; int height; } there is no physical difference, but a conceptual one. Off of my head, I'm guessing Joel Spolsky would use COORD to represent both, then prefix variable with vec- dim- Is that "usage" or "type"? I don't think there is a practical difference. Different (or special) usage implies a new type to me.

Actually he means *usage of a type*. For his example he has 2 different kinds of strings that diff in their contents, but not their capabilities. It would be pretty useless to make class EncodedString {..} class UnEncodedString {...} just to make the point that one needs to be Encoded before it can be displayed on a web page. Using your example, perhaps the width and height are floats, but represent the percentage of the parent window? Sometimes they represent screen coordinates. Other times window coordinates. The same could apply for coordinate. You _could_ make separate classes for this purpose, and write reams of code for conversions and whatnot(and with each page of code and interlocking methods your code becomes harder to maintain). Or you could just use the conventions he talks about. I think the gist of it is, when you rely on the type system too much perhaps you don't understand the flow of your program well enough and are prone to mistakes. -DavidM
Jun 01 2005
parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
David Medlock wrote:
 Hasan Aljudy wrote:
 
 David Medlock wrote:

 Brad Beveridge wrote:

 David Medlock wrote:

 Regan Heath wrote:

 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.

 Regan

His point with App-Hungarian notation is correct, that variable usage is more important than just a variable's type. His underlying theme( which I agree with 110% ) is that your programming idioms are vastly more important than the underlying constructs used to implement them. -DavidM

Really, what it boils down to is "give your variables sensible names". D has strict typedefs so you can create new types, which the compiler will complain about. Ie, from his row/col example typedef int rowType; typedef int colType; rowType r; colType t; r = t; // D compiler will catch this. So, if you want to write truely robust code you can create a slew of new types to ensure that any conversion from type to type will not be implicit. Brad

Yes, but his point(and Raymond Chen's) is that you do not prefix based on *scope* or *type* but usage. I think this is more powerful than the others. Really does it matter that a x coordinate is an int, or that is is a class or module variable? No, just that it represents screen coordinates. -DavidM

By variable usage, you mean "what it represents"? well, for me, that's a type (read: class). What's the difference between struct vector { int x; int y; } and struct dimension { int width; int height; } there is no physical difference, but a conceptual one. Off of my head, I'm guessing Joel Spolsky would use COORD to represent both, then prefix variable with vec- dim- Is that "usage" or "type"? I don't think there is a practical difference. Different (or special) usage implies a new type to me.


 Actually he means *usage of a type*.

purpose2. If you're gonna use one type to represent different things, it'd be alot better to define X2 and use it for purpose2. What's the difference between a wchar and an unsigned short? They're both numbers, and in the C family of languages, you can do things like int a = 't'; so why would you use a "char"?
 Actually he means *usage of a type*.  For his example he has 2 different 
 kinds of strings that diff in their contents, but not their 
 capabilities.  It would be pretty useless to make
 
 class EncodedString {..}
 class UnEncodedString {...}
 
 just to make the point that one needs to be Encoded before it can be 
 displayed on a web page.

Actually, you'd make something like a DefensiveString and subclass SafeString and UnsafeString from it. (read my other reply digitalmars.D/24901) Yes, there is a different behaviour for these strings .. it's not "just to make the point that one needs to be Encoded .....". It's to prevent the kind of bugs where you accidently print an unsafe string without encoding it first, hence opening yourself up for bugs. (read my other reply to understand what I mean).
 
 Using your example, perhaps the width and height are floats, but 
 represent the percentage of the parent window?  Sometimes they represent 
 screen coordinates. Other times window coordinates. The same could apply 
 for coordinate.  You _could_ make separate classes for this purpose, and 
 write reams of code for conversions and whatnot(and with each page of 
 code and interlocking methods your code becomes harder to maintain).

These examples are not necessarily different types of coordinates. They are still coordinates. However, if in your program, there are different types of coordinates that need to be treated differently, then it'd be a good idea to subclass and redefine some behaviour for these coordinates.
 
 Or you could just use the conventions he talks about.
 

 I think the gist of it is, when you rely on the type system too much 
 perhaps you don't understand the flow of your program well enough and 
 are prone to mistakes.

Actually, OOP is used to manage complexity, and it does it times better then the procedural way. With his way, you can easily forget the rules and write string sName = Request("Hello"); specially when you have so many such rules and the size of the project is too big. With my way, you can't do anythign like SafeString name = Request("Hello"); because the request function knows that user input is not safe, so it returns an UnsafeString. And even if it did return just DefensiveString, polymorphism would take care of the line: Print(name.getString()); //get string knows that name is unsafe, so it'll return it in an encoded form where as with his way, you can easily write Print(sName); Niether you nor the compiler will see anything wrong with this. and don't tell me that you can spot the error in "string sName = Request("Hello");", because you simply can't guarantee that. I mean, hell man, alot of us still make the mistake of doing if( x = y ) and spend hours on end trying to find where the problem is without noticing this silly mistake. You simply can't ensure that you can keep track of every rule you make for yourself and be able to ensure that every line of code complies to these rules.
Jun 01 2005
prev sibling parent "Jim H" <jhewesNOSPAM ix.netcom.com> writes:
"Brad Beveridge" <brad somewhere.net> wrote in message 
news:d7l58u$2fq5$1 digitaldaemon.com...

 Really, what it boils down to is "give your variables sensible names".

Agreed. You can invent some special naming convention. But why can't you just name your variables sufficiently well? Instead of "rwMax", you could write "rowMax" or "MaximumNumberOfRows". If you are trying to say that something prefixed with "rw" should not be assigned to something prefixed with "col", then you may be talking about two different types and you should try to use the language to express them that way if possible rather than using identifier names as a poor man's type system. I'm not necessarily saying that his style tip is bad. It's an extra layer of checking. But I'd rather not depend totally on human eyes to catch problems. That why we have computers. In reading that article and a couple of the links it references, I again get that sense of Microsoft programming style that I get in their API design and sample code. Sometimes accomplishing anything takes many lines of code and several function calls. It's as if they are saying, "How do you create a widget you ask? You just call this sequence of 35 functions and voila! You're done! Easy. What's your problem?" I'm sure they are very smart and can keep those long functions of procedural code in their head and it seems perfectly normal to them. Encapsulation is bad because it hides things; you should have everything in front of you so you know everything what's going on. I could be completely off-base about this, but based on the articles it seems like perhaps Spolsky and Chen think in a more procedural way rather than OOP. Jim
Jun 04 2005
prev sibling parent "Unknown W. Brackets" <unknown simplemachines.org> writes:
Another method of the "unsafe" thing is to make all strings "safe" by 
default, in a way.  Different systems do this in different ways - for 
example, Mambo (a CMS) will strip HTML from all user input by default, 
unless it is told not to.

It really comes down to knowing what you're doing.  To me, code that is 
wrong (by my coding standards and the way I typically clean variables) 
does look wrong - without prefixes.  Part of this is not copying or 
referencing around unsafe data - that's just dumb right off, to me.

Prefixes just break up the readability of code.  Reminds me of 
QuickBASIC, where you used different symbols for different types.

-[Unknown]


 http://joelonsoftware.com/articles/Wrong.html
 An article by "Joel Spolsky".
 I loved it.
 
 Regan

Jun 01 2005