users
[Top] [All Lists]

Re: [cinjug-users] Brandan Jones Presentation

To: esumerfd@xxxxxxxxxxxxxx
Subject: Re: [cinjug-users] Brandan Jones Presentation
From: <inmanjon@xxxxxxxx>
Date: Wed, 18 Oct 2006 11:52:59 -0400
Cc: "users@xxxxxxxxxx" <users@xxxxxxxxxx>
Delivered-to: mailing list users@cinjug.org
Mailing-list: contact users-help@cinjug.org; run by ezmlm
Sensitivity: Normal
Cinjug does rock....

This guy was actually knighted for his work in this Computer Science and he was 
an assertion freak.

http://research.microsoft.com/~thoare/

His basic premise is that programmers are the cause of ALL the high costs in 
development projects, and quite frankly they are.

Assertions are a way of forcing programmers to remove that costs.

Example:
(pseudo code)
function importantMethod(Int x, String s) {

    assert(x is an integer if it shouldn't be null say why)
    assert(s is a string and why it should be a certain length if required)

}

This is FAR cheaper than debugging 20 lines into a method and realizing a 
variable is invalid, ESPECIALLY if it is somebody elses code.

To quote Tony(yes we are on a first name basis)

  ASSERT ( assertion, âreason why I think
                 the assertion is trueâ)
        
  â   Otherwise itâs easy to forget
        
  â   Helps both writer and reader.

To newbies this might seam silly, but I get a warm fuzzy feeling all over when 
I step through the assertions before entering method guts.

With 1.5, Java has a way of compiling ASSERTIONS out of code when you deploy, 
does anybody use this?

Later...

---- Edward Sumerfield <esumerfd@xxxxxxxxxxxxxx> wrote: 
> A great presentation by Brandon last night. As always, I learned
> something new. CinJug rocks.
> 
> It sounded like there were some java newbies there so I thought it
> would be interesting to pick apart the parts of Brandon's code that
> were bad. I hope all the newbies are on the list and that no one takes
> "newbie" in any derogatory sense.
> 
> We all understand that Brandon's presentation was focused on Patterns
> so this is no reflection on his code since it served its purpose well.
> Instead it may serve as a fun extension to that code to look at what
> is good and bad about what we do each day.
> 
> If you don't recognize my name and were at the meeting you will know
> me by "I am the runner, execute".
> 
> Exceptions
> ----------------
> The exceptions were used in the file io process and it brings up lots
> of good practice issues.
> 
>     try {
>         Scanner scanner = new Scanner(file);
>         ...
>     }
>     catch (FileNotFoundException e)
>     {
>         throw new RuntimeException(e);
>     }
> 
> 1) Should we every throw a RuntimeException?
> 
> Your applications should never throw or catch Exception or
> RuntimeException. Instead, your application should use a well defined
> exception hierarchy that allows exceptions to be addressed at
> appropriate levels.
> 
> In this case we should throw something like
> FileNotFoundRuntimeException. There might also be an
> InvalidFileFormatRuntimeException that can be thrown if the scanner
> doesn't find what it expects. This is text based UML, where ^ means
> extends.
> 
>     RuntimeException
>         ^
>     FileImportFailedRuntimeException
>         ^                                                                  ^
>     InvalidFileFormatRuntimeException     FileNotFoundRuntimeException
> 
> With this structure the thrower can now throw an exception that is
> specific to the problem. The catcher can catch the specific or the
> higher level exception depending on how they want to manage the
> problem.
> 
> 2) Should we use checked or unchecked exceptions?
> 
> There is a great deal of debate in the industry about which are the
> better approach. You will tend to find that people that like strongly
> typed languages also like checked exceptions, where as those who
> prefer dynamically typed languages tend toward the unchecked variety.
> 
> I will give you my perspective and let others posture the alternatives.
> 
> Checked exceptions force the user of an API to deal with the problems
> that the API might cause. At first sounding this seems good.
> Unfortunately, in reality the "force" portion of this  process is
> thrust upon the developer before they really know what the program
> should do about it. The result is that code gets a lot of empty catch
> blocks or System.out.println's.
> 
> The hardest bugs to find are those that don't leave any evidence and
> empty catch blocks are the worst. Even works that null pointer
> exceptions but we will get to those next.
> 
> I am a proponent of forcing real errors to the surface as fast as
> possible which means crashing the program in front of the developer.
> To do this I propose only using RuntimeExceptions and allowing the
> developer to choose the best time and place to insert the catch
> statement.
> 
> When the developer has got to the point of running the program and
> finding the error situation they are at the right point to know what
> to do about it and can insert the catch of the runtime exception and
> the appropriate behaviour.
> 
> The other advantage of the RuntimeException is that you don't have to
> declare it on all the methods that might end up calling a thrower.
> This loosens the coupling between your APIs and reduces the number of
> files that change when you change you mind about the exceptions to
> throw.
> 
> Nulls
> -------
> One of the early versions of Brandon's factory method went something like 
> this:
> 
>     if (param.equals("something")) {
>         return new Something();
>     }
>     else if (param.equals("anotherthis")) {
>         return new AnotherThing();
>     }
> 
>     return null;
> 
> Nulls are the death of a system. Traditionally developed software
> follows a few predictable phases, code, test, fix bugs, release to
> production, fix all the null pointer exceptions.
> 
> These bugs are hard to find because the exception report doesn't tell
> you where the error occurred, only where the null value was eventually
> used.
> 
> The most common fix is "if (x != null)". This is not the right answer
> but sometimes we are forced into bad code by bad 3rd party libraries.
> What can I say, most of them suck. Yes, I am opinionated, and they
> still suck.
> 
> The correct answer is to not produce nulls. If no code ever returns a
> null then you will never get a NullPointerException.
> 
> Brandon's final version converted over to throwing an exception (not
> the correct type but we have talked of that already) so the factory
> can not produce a null.
> 
> Take this to the next level. A method getList(). What should it do if
> there is no list available. It should return an empty array list. Sun
> was kind enough to supply is with a simple version in
> Collections.EMPTY_LIST or emptyList in 1.5.
> 
> In all cases there are ways to design your APIs to prevent nulls from
> being produced. Take the extra time to do this because you will earn
> it back in droves as you sit back and watch your not so well educated
> colleagues shouting about a bug that "just can't be happening".
> 
> Single Return Statements
> -------------------------------------
> This one is slightly contentious as well. A method should only have
> one return statement in it. Brandon's original factory method had 4.
> This becomes a real problem in longer methods when you can't always
> tell if the code nearer the bottom will get executed.
> 
> Ideally all you methods should be short as well but these features
> play against each other as a nice piece of code gets hacked on by 20
> different developers over a few years.
> 
> Some argue that in short methods it doesn't matter. I argue that short
> methods become long methods so it always matters. I never use more
> than one return statement even on the simplest cases.
> 
>     MonthlyCommand command;
> 
>     if (param.equals("something")) {
>         command = new Something();
>     }
>     else if (param.equals("anotherthis")) {
>         command = new AnotherThing();
>     }
>     else {
>         throw new InvalidFileTypeRuntimeException("Ooops");
>     }
> 
>     return command;
> 
> Brandon's final reflective approach got rid of this problem anyway and
> you will find that good design principles will tend to get rid of
> these bad coding habits auto magically. It's all about the the strong
> karma that you develop with each excellent piece of code.
> 
> DRY
> ------
> Don't Repeat Yourself. We all know that we shouldn't duplicate code.
> Copy Paste is a bugs best friend, the easiest way to spread through a
> system. Brandon's code ended up with a set of MonthlyCommand
> implementations that included a try catch for FileNotFoundException, a
> scanner and a set of file specific fields.
> 
>     public void execute(file) {
>         try {
>             Scanner scanner = new Scanner(file);
>             String name = scanner.next();
>             String amount = scanner.nextInt();
> 
>             System.out.println(name + " " + amount);
>         }
>         catch (FileNotFoundException e)
>         {
>             throw new NoInputFileRuntimeException("Could not find
> input file", e);
>         }
>     }
> 
> So how DRY is this code. There are four lines of duplicate code here.
> Lets try a simple pull up refactoring to get rid of them:
> 
> First in the abstract base class.
> 
>     public void execute(file) {
>         try {
>             Scanner scanner = new Scanner(file);
>             parseFields(scanner);
>         }
>         catch (FileNotFoundException e)
>         {
>             throw new NoInputFileRuntimeException("Could not find
> "+file.getName(), e);
>         }
>     }
> 
>     protected abstract void parseFields();
> 
> Then in the original MonthlyCommand implementation that is not
> extending our abstract base class.
> 
>     public void parseFields(Scanner scanner)
>     {
>             String name = scanner.next();
>             String amount = scanner.nextInt();
> 
>             System.out.println(name + " " + amount);
>     }
> 
> It's a very simple change, it centralizes the error handling which is
> really important and cuts down the amount you have to type in for each
> command you write. You know there is a limit to the number of keys you
> can press in a lifetime, use them wisely.
> 
> Open Close Principle
> -------------------------------
> Brandon talked about using these patterns to reduce the number of
> classes that you have to edit to add new functionality. This is called
> the Open Close Principle. Once you live by this you will significantly
> improve the quality of the API's that you design.
> 
>     Code should be open for extension
>     and closed for modification.
> 
>     http://en.wikipedia.org/wiki/Open/closed_principle
> 
> Unit Tests
> --------------
> Brandon mentioned his commitment to unit testing at the end of the
> presentation. I hope everyone took this to heart. Test first
> development (also called Test Driven Development) is the most
> significant advancement in software engineering practice since OO.
> Every class/method you write must have a corresponding unit test.
> 
>     http://en.wikipedia.org/wiki/Test_driven_development
> 
> I know there are a few Universities starting to teach TDD but it is by
> no means mainstream yet. Most professionals already working today do
> not have an understanding of TDD. We still live in a world of "let the
> QA group do the testing for me".
> 
> If I interview someone that doesn't know or use TDD, I will not hire
> them. It's that simple.
> 
> Perhaps Brandon can comment on how he addresses this subject.
> 
> Thanks again for the presentation Brandon.
> 
> -- 
> Ed
> 
> ---------
> You may unsubscribe from this mailing list
> by sending a blank email addressed to:
> users-unsubscribe@xxxxxxxxxx
> 
> --
> Find additional help by sending a blank email
> addressed to:
> users-help@xxxxxxxxxx
> 


<Prev in Thread] Current Thread [Next in Thread>