Upload
carlee-ellingsworth
View
222
Download
3
Embed Size (px)
Citation preview
Becoming a Better
Developer
Things I have learned...
... that has made me to a better developer ...
... than I was before I learned them
Johannes Brodwall
Lead Software Architect, BBS
Organizer, Oslo XP Meetup
Board-member, Oslo Agile UG
Committee member, ROOTS conference
Slides:
• http://www.brodwall.com/johannes/blog/• http://www.brodwall.com/johannes/blog/2006/08/28/tips-for-developers/
Experience Report
Things I have learned...
... that has made me to a better developer ...
... than I was before I learned them
(2)
Be brief
"I would have written a shorter letter but I didn't have the time.“- Mark Twain
(1)
Accept failure
(But only settle for perfection)
Developer or coder?
Coder: A good coder writes good code
Programmer: A good programmer is a good coder who thinks well
Developer: A good developer is a good
programmer who communicates well
The Word: Versatility
Define: Versatility
”having a wide variety of skills”
Know a lot about somethingAnd something about a lot
(3)
In-depth knowledge
Code:
public void testFoo() { try { int result = bar.doBar(); assertEquals("should be 0", 0, result);
} catch (BarException e) { fail("illegal exception caught");
} }
public void testFoo() throws BarException { int result = bar.doBar(); assertEquals("result", 0, result); }
Socket s = null;try { s = new Socket(”server”, 12345);} catch (IOException e) { log.error(”An exception occurred”, e);}
InputStream in = s.getInputStream();
Exception Handling
Socket s = null;try { s = new Socket("server", 12345);} catch (IOException e) { log.error("An exception occurred", e); throw new CustomException(e);}
InputStream in = s.getInputStream();
try { Socket s = new Socket("server", 12345); InputStream in = s.getInputStream();} catch (IOException e) { throw new CustomException(e);}
Catch block? Probably bug
Johannes’ first rule of exceptions
”There is usually nothing you can do”
Source controlUnit testing
Continuous Integration
What is a task?
What is a good task?
”How will I know when it is done?”
(How about: The tests passes)
public void testProcessFile() throws IOException { processor.process(file); assertEquals(StatusCode.PROCESSED,
file.getCurrentStatusCode()); assertEquals("transmissions", 1,
file.getTransmissions().size());
Transmission transmission = file.getTransmissions().iterator().next(); assertEquals(3,
transmission.getTransactions().size()); assertEquals("transactionSum", new Money(7000, Currency.getInstance("NOK")), transmission.getTransactionSum());
Code perfection
• From: http://today.java.net/pub/a/today/2006/07/13/lazy-loading-is-easy.html
Category category = dao.get(1);Category parent = dao.get(category.getParentId());List children = new ArrayList();for (Long childId : parent.getSubcategoryIds()) { children.add(dao.get(childId));}System.out.println(children);
Category category = dao.get(1);System.out.println(category.getParent().getSubcategories());
Exploit Defaults
<class name="BookCategory" table="book_category"> <id name="id" column="id" access="property"
type="long"> <generator class="native" /> </id>
<property name="name" column="name” insert="true" update="true” access="property" />
<property name="creationYear" column="craton_year" insert="true" update="true" access="property" />
No: You are not special
<class name="BookCategory" > <id name="id"> <generator class="native"/>
</id>
<property name="name"/> <property name="creationYear"/>
No: You are not special
This gives tablename: bookcategory
But we wanted:book_category
No: You are not special(except when you are)
<bean id="hibernateSessionFactory”class=”...LocalSessionFactoryBean">
<...> <property name="namingStrategy” ref="hibernateNamingStrategy"/>
</bean>
<bean id="hibernateNamingStrategy”class=”...ImprovedNamingStrategy"/>
No: You are not special
• Sun/Apache/Rod Johnson/DHH/Gavin King is probably smarter than you
(4)
Don’t overspecialize
Specialization is for insects!
Learn a different programming language
• Javascript example: http://joelonsoftware.com/
function sum(array){ return reduce(array, 0, function(a, b){ return a + b; });
}
function sum(array){ return reduce(array, 0, function(a, b){ return a + b; }); }
sum([1, 2, 3, 4, 5]); => 15
function sum(array){ return reduce(array, 0, function(a, b){ return a + b; });
}
function reduce(array, initial_value, fn) { var result = init; for (i = 0; i < array.length; i++) result = fn( result, array[i] ); return result;}
function sum(array){ return reduce(array, 0, function(a, b){ return a + b; });}
Object sum(Collection collection) { return reduce(collection, 0, new BinaryFunction() { public Object doIt(Object a, Object b) {
return (Integer) a + (Integer) b;
} });}
Practical use in Java
• Lazy Loading Example: http://today.java.net/pub/a/today/2006/07/13/lazy-loading-is-easy.html
Parent getById(final long parentId) { ResultSet rs = ....; Parent parent = transformFromRs(rs); parent.setKids( (Collection)lazyLoad(new LazyLoader() { public Object loadObject() { return kidsByParentId(parentId) } }); return parent;}
function getById(parentId) { var rs = ....; var parent = transformFromRs(rs); parent.kids = lazyLoad( function() { return kidsByParent(parentId); }); return parent;}
JavaScriptScheme
Ruby
Developer or coder?
Coder: A good coder writes good code
Programmer: A good programmer is a good
coder who thinks
(5)
See the bigger box
”There is no use in trying,” said Alice. ”One cannot
believe impossible things”
”I daresay you haven’t had much practice,” said the
queen.
”When I was you age, I always did it for half an hour
a day. Why, sometimes, I believed as many as six impossible things before
breakfast”• Lewis Carroll: Through the looking glass
How many Petals Around the Rose
• http://illuminations.nctm.org/LessonDetail.aspx?id=L576
Disclaimer: Riddle-solving doesn’t measure
intelligence
(My wife solved this one faster than me)
How many Petals Around the Rose
How many Petals Around the Rose
• Answer: 10 petals around the rose
How many Petals Around the Rose
How many Petals Around the Rose
• Answer: 6 petals around the rose
How many Petals Around the Rose
How many Petals Around the Rose
• Answer: 0 petals around the rose
“The most profound discoveries never begin
with EUREKA!
Usually they start with the words "now that's odd..."
How many Petals Around the Rose
How many Petals Around the Rose
• Answer: 6 petals around the rose
How many Petals Around the Rose
How many Petals Around the Rose
• Answer: 2 petals around the rose
Solve it yourself
• http://illuminations.nctm.org/LessonDetail.aspx?id=L576• (Or my blog)
– http://www.brodwall.com/johannes/blog/2006/07/22/thinking-outside-the-box/
Ask ”why”
Why are we doing this?
• Why are you writing ”pay for order” functionality?– Because it is needed for the user to pay for the ticket
order service
• Why are we writing the ticket order service?– Because it is our project mandate to deliver an online
ticket system
• Why is an online ticket system our mandate?– Because we believe that with our expertice in
interactive web solutions, we can offer a really good service
”Why am I writing this”
From: JohannesTo: BjørnSubject: Build server is down
Hi, BjørnThe build server is down.
~Johannes
What do you expect the recipient to do?
From: JohannesTo: BjørnSubject: FYI: Build server is down
Hi, BjørnFor your info: The build server is down. I am currently investigating and will let you know as soon as I know more.
~Johannes
From: JohannesTo: BjørnSubject: Please get the build server up again
Hi, BjørnThe build server is down. Can you get it fixed?
~Johannes
Communications is
Communications is not explaining
Communication is creating a shared
understanding
(6)
Coupling
Secret to good design:Avoid bad coupling
Exploit good coupling
”Two things are coupled if change to one requires
change to the other”
Avoiding bad coupling
Programming by intention
public void testCategoryIsStoredCorrectly() { Category category = new Category("category
name", 1999); category.addSubcategory(new Category("foo")); category.addSubcategory(new Category("bar"));
Object id = dao.save(category); dao.flushCache();
Category copy = dao.get(id); assertNotSame(copy, category); assertAllFieldsEquals(copy, category);}
(Hiding details)
public void testSearchForNameAndCreationYear() { Collection expected = new HashSet();
storeMatching(new Category("magic 1",1999), expected, dao);
storeNonMatching(new Category(”non-magic 2",2000), dao);
CategorySpecification specification = ...;
Collection actual = dao.find(specification); assertCollectionHasSameElements(”find " +
specification, expected, actual);}
Avoiding repetition
Comments repeating codeCode duplication
Duplicated decisions
<class name="BookCategory" table="book_category">
<id name="id" column="id"> <generator class="native" /> </id>
<property name="name” column=”name" /> <property name="creationYear" column="creation_year" />
(7)
Haste != Productivity
Johannes’ only rule for crisis management
Don’t just do something
Stand there!
Productivity = Getting Things Done
What is a good task?
”How will I know when it is done?”
”How will someone else know when it is done?”
Tip: Offload your task list from your brain
Yellow notesOutlook: Flags and Tasks
Gmail: Inbox
Tip: Do it now, Do it soon,
Defer it, Delegate it, or Drop it
The Art of the Two-Minute Email
Follow up on what you defer and delegate
(8)
Myopia (nearsightedness):the inability to see distant objects
as clearly as near objects.
Myopia is good for your health
Implement for today
Not for tomorrow
”We have to write this as a web service in case
someone someday want to integrate with us”
Enterprisey!
Not for yesterday
• From http://antipatterns.org/
” This class was written by some earlier (Alex?) to manage the indexing of something (maybe). It is probably
important. Don't delete. I don't think it's used anywhere - at least not in the new
MacroINdexer module which may actually replace what it was used for.”
• Credit: AntiPatterns
(9)
Leave proud
/** TODO: Write a better comment. * @param foo * @return */ public boolean checkIt(String foo) { StringBuffer buffer = new StringBuffer(); buffer.append(foo); buffer.append("@"); if (getStuff().startsWith(buffer.toString())) { return true; } else if (!getStuff().startsWith(buffer.toString())) { return false; } else { return false; } } }
/** TODO: Write a better comment. * @param foo * @return */ public boolean checkIt(String foo) { StringBuffer buffer = new StringBuffer(); buffer.append(foo); buffer.append("@"); if (getStuff().startsWith(buffer.toString())) { return true; } else if (!getStuff().startsWith(buffer.toString())) { return false; } else { return false; } } }
TODO comments
Skeleton javadoc
Premature (and unneeded)
optimization
Very common verbositis
Common unthinking
public boolean isUsernameEqual( String username) { return getEmailAddress(). startsWith(username + "@");}
(2)
Be brief
”Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”(Antoine de Saint-Exupery)
(1)
Accept failure
"Knowing the pathis not the same as walking
the path”- Tao te Ching
Summary
1. Accept failure2. Be brief3. In-depth knowledge4. Don’t overspecialize5. See the bigger box6. Eliminate bad coupling7. Don’t just do something, stand there8. Work for today9. Leave proud