Thread overview | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 01, 2005 Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
http://joelonsoftware.com/articles/Wrong.html An article by "Joel Spolsky". I loved it. Regan |
June 01, 2005 Re: Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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.
|
June 01, 2005 Re: Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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
|
June 01, 2005 Re: Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Anders F Björklund | Anders F Björklund wrote: > Regan Heath wrote: <snip> > Exceptions and gotos are both bad, and error codes are > much better. And all the extra idents makes it easier? <snip> 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 |
June 01, 2005 Re: Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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
|
June 01, 2005 Re: Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Medlock | 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
|
June 01, 2005 Re: Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Brad Beveridge | 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 |
June 01, 2005 Re: Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Brad Beveridge | 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.
|
June 01, 2005 Re: Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | 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.
>
I like that - I don't think I've seen that idiom before. I'm a bit of a 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
|
June 01, 2005 Re: Make code that is wrong, look wrong... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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
|
Copyright © 1999-2021 by the D Language Foundation