CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo [MVP]

Software management consultant and CTO, Headspring Systems

NFJS: Cleaning up your code with Neal Ford – level 200

Neal gave some great tips on improving code.  Here’s the rundown.  These are thoughts directly from Neal:

Coding standards aren’t necessary.  They are just preferences that folks in charge force on underlings.  There are more important things than coding standards.  Tools can reformat code to some sort of standard.

#1:  Naming things:  Use verbose variable names.  Don’t worry about having to type.  Modern IDEs give you these in a drop-down list, so you only have to type them once.  IntelliJ and Resharper will guess, and you don’t have to even type them once.

#2:  Composed Method:  Comments.  Xml comments are sometimes useful if you need to generate documentation.  Intra-code comments are not necessary most of the time.  No one ever reads them, they smell, and they lie when the code around them changes (because no one updates them).  There is nothing that anchor line comments to the code they are supposed to describe.  At least Xml comments are anchored to the method.  So, if comments in code don’t help as much as we’d like, what can we do?  Make the method name be a long, description of what the method does, and no method should be longer than 5-15 lines of code.  All public methods should read as an outline of things that need to be done (and call private methods to get these things done).

  • Benefits of compose method
    • Stack traces become easier to read
    • Debugging is easer.  Instead of stepping over lines of code, you step over private methods that are little chunks of work.
    • It makes writing unit tests easier because you can fake out any step.
    • It makes it easier to identify generic methods that can be pushed up the inheritance hierarchy.
    • Once the method reads easier, line comments become redundant and unnecessary.

#3:  Apply the Unix Philosophies:  By applying unix principles to software will make it better. 

  • Write simple parts connected by clean interfaces.
  • Clarity is better than cleverness.
  • Design programs to be connected to other programs
  • Separate policy from mechanism; separate interfaces from engines.
  • Design for simplicity; add complexity only where you must
  • Write a big program only when it is clear by demonstration that nothing else will do.
  • Design for visibility to make inspection and debugging easier.
  • Robustness is the child of transparency and simplicity.
  • Fold knowledge into data so program logic can be stupid and robust.
  • In interface design always do the lease surprising thing.
  • When a program has nothing surprising to say, it should say nothing.
  • When you must fail, fail noisily and as soon as possible.  (Don’t return null if something really bad happens).
  • Programmer time is expensive; conserve it in preference to machine time.
  • Avoid hand-hacking: write programs to write programs when you can.
  • Prototype before polishing. Get it working before you optimize it.
  • Distrust all claims for the “one true way”.
  • Design for the future because it will be here sooner than you think.

#4:  Syntactic Stuff: 

  • If a constant is tied to a particular class, it should be defined within the class.
  • If a constant is not tied to a class, it should be tied to an interface.  Don’t implement a class for the constant.  You should use the constant through the interface name.
  • In Java, you can use the javax.print.attribute package and inherit from the EnumSyntax class.  Java 5 has native support for Enums as does .Net, but safe enumerations that are ranged-checked are important.
  • How to implement equals()
    • Use == to see if you have been passed yourself.
    • Use instanceOf to check the lineage of the object.
    • Check the equality of each field in your class.  If any test fails, return false.
  • Any time you override equals(), you should override GetHashCode(). 
    • If two objects are equal, they must return the same hash code. 
    • It’s not required that two unequal objects return different hash codes, but collection performance could suffer.
    • IntelliJ is smart enough to generate good equals() and hashCode() methods.  I’ll have to check to see if Resharper will do this.

#5:  Orthogonality: the absence of side-effects.

  • Command/query separation:  You should not do two things under the guise of one.  Don’t calculate something if you name it “get”.
  • For example, in a Stack class, if you call “pop”, you remove something just to read it.  If an error happens, you’ve lost the object.  A more orthogonal approach would use a “top” method and “removeTop” method.

#6:  Don’t repeat yourself.

·         DRY principle.  Every piece of information should have one authoritative representation.

·         If you have an NHibernate mapping, you could generate it from the database schema (if you have a 1-1 mapping). 

·         If you want documentation of your system, you should find a way to generate the documentation from the code.

o       yDoc is a commercial documentation product that generates UML.

#7:  The Methodology Rules

·         Don’t live with broken windows:  If you have a broken window, it indicates that nobody cares.  If you leave it there, your source code is fragile.  Your code will get stronger over time if you are adamant about automated testing and fixing broken windows.

·         From Agile Best Practices:

o       YAGNI – You ain’t gonna need it.  If you aren’t absolutely sure you need it right now, defer it until later.
o       Embrace changing requirements by:

·         Refactoring mercilessly

·         Set aside time every day to refactor code.

·         Refactoring is fun, and it is different from “regular” coding.

·         Automated testing.

·         Test coverage gives confidence that you have changed some code, and you haven’t broken anything.

·         Testing is a frame of mind, not a tool set.

·         Who cares if the test was written first or last as long as the code and test are written close together.

·         Applications tend to grow from the bottom up with small, little units of verified code.  The alternative is writing top down (which is hard).

·         Generate code coverage reports on your tests.

#8:  Template method design pattern.

  • If you know what the algorithm should look like but don’t know the details, you can write the outline and defer the details to child objects.
  • It encourages your to define the general order of operations for some process in an abstract parent, then implement the details in child classes.
  • This works best when the code is small, cohesive, and discrete.
  • You should aggressively pull methods up the hierarchy and look for definable processes.

#9: Bad Inheritance.

  • Inheritance is hard, so use composition instead of inheritance.  Encapsulate the type you were going to override and forward calls to it.
  • Inheritance is only applicable when the child “is-a” type of the parent in EVERY case.

#10:  Use interfaces for decoupling

  • Whenever possible, define types and member variables as interfaces.
  • If you have a class that needs to act as two things, you can implement two interfaces.
  • Objects are more flexible because they can be treated as either a base class or an interface that’s implemented.
  • This allows libraries to be written that are not bound to specific classes.

The result of all this is framework code and configuration.  Framework code is common code that’s pulled up.  The code with the details is configuration.  The end result is a domain specific language that comes out of the APIs that result.

Neal’s final point is that code is the most important artifact we create.  If you create the most brilliant piece of software with not documentation and not bugs, you’ll be a hero.  If you create beautiful documentation without good software, you won’t be worth anything.



About Jeffrey Palermo

Jeffrey Palermo is a software management consultant and the CTO of Headspring Systems in Austin, TX. Jeffrey specializes in Agile coaching and helps companies double the productivity of software teams. Jeffrey is an MCSD.Net , Microsoft MVP, Certified Scrummaster, Austin .Net User Group leader, AgileAustin board member, INETA speaker, INETA Membership Mentor, Christian, husband, father, motorcyclist, Eagle Scout, U.S. Army Veteran, and Texas A&M University graduate. Check out Devlicio.us!

This Blog

Syndication