Tuesday, April 13, 2010

Moving people around, Pairing


Move People Around:

Pair Programming:


Some fun pairing rules (guidelines) you can print out and stick on a wall maybe once people have tried pairing for a few weeks:

Some lessons you can probably only learn by trying it first and seeing what works in your environment:


Dirty Secret
http://agilesoftwaredevelopment.com/blog/mendelt/dirty-secret-pair-programming

Ron Jeffries
http://www.xprogramming.com/Practices/PracPairs.html

Stability and Acyclic Dependencies Principle

http://www.objectmentor.com/resources/articles/stability.pdf


The dependency structure between packages must be a Directed Acyclic Graph (DAG). That is, there must be no cycles in the dependency structure.

Single Responsibility Principle

http://www.objectmentor.com/resources/articles/srp.pdf


The SRP is one of the simplest of the principle, and one of the hardest to get right. Conjoining
responsibilities is something that we do naturally. Finding and separating those
responsibilities from one another is much of what software design is really about. Indeed,
the rest of the principles we will discuss come back to this issue in one way or another.

Getters and Setters are evil

http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

Avoiding software rot





I think this web page is very relevant to where we are right now as a dev team: http://www.agile-process.org/change.html  (copied below with my emphasis) 
(agile-process.org has many pages well worth the read - it's the sort of site you want to come back and read every 6 months)

I think the key here is that if we're going to be agile, our codebase needs to be agile... i.e. easy to change
This means:
- code is always refactored - the next person doesn't have to tidy it up before they can begin
- code is fully tested (unit and acceptance) - so the next person doesn't have doubts about whether it works or not, they can re-design with confidence knowing the tests have got their back... And so we don't have bugs lurking around in dark areas of the code - bring it into the light!  Prove that it works!
- code follows conventions agreed on by the team - so the next person doesn't have to figure out why this code is different to the rest of the codebase
- there is no code duplication - we reuse code - rather than duplicating bugs / bad logic / unnecessary boilerplate code - we put it in one place so it can be easily changed
- code is simple - testable, understandable, browsable, explainable

Lots of good decisions in the small result in big payoffs in the large... lazy decisions in the small result in unmaintainable code... read on :)




Surprise! Software Rots!




Is software designed to be simple and elegant more valuable than software that is complex and hard to maintain? An Agile process accepts this as an important fact.
 It may surprise you to learn software rots. Intellectually we know it really doesn't, but it might as well. Software rot is caused by improper design and limited project resourcesComplexity creeps in as easy code changes are made instead of difficult design changes. Code duplication accumulates rapidly during maintenance tasks.
 After a while we notice that fixing one bug causes several even more subtle (and expensive) bugs to occur and the cost of maintenance goes up significantly. Eventually the cost of maintenance exceeds resources. It seems as if our code has decayed on its own in spite of our best efforts.
 Berry Boehm found that as software proceeded through its life cycle the cost of making a change became larger. Ratios of 100:1 for making a change after delivery versus project start are common. But ratios as low as 5:1 can be found. How flat this curve stays depends on many individual project factors.
 This cost curve is commonly interpreted to mean that you must create infallible requirements documents followed by complete, detailed, and
Boehm's cost of change curve
error-free designs or pay a huge price later. That isn't what it means. Boehm's findings are not a condemnation of change but rather a caution tobe prepared when changes occur. A well run project keeps the cost of changes lower longer.
 There are three life cycle events that seem to accelerate software rot. When we proclaim the design is done and accept no more changes. When we move the system into maintenance and change the team's process. Last when the cost of making vital changes exceeds our resources we reach the wall of unmaintainability.
 To stay Agile you must fight software rot. Refactoring is the art of making design changes over time to keep the software fit for its purpose and ready for more changesUnitand acceptance tests can almost eliminate the fear that drives inappropriate easy changes on a delivered
system. Early delivery of partial systems helps detect big changes before they become expensive. An Agile process accepts that requirements, analysis, and design are never truly done. An Agile process runs equally well in maintenance or development easing the transition.
 We know that some changes will cost much more than others. Boehm's findings were that 20% of the changes make up 80% of the effort. We accept that. We counter it with honest estimates and use a planning process that requires the customer to guide our spending decisions and cost compromises. We fight software rot from start to finish so it can never dominate our decisions.
 Agile processes are a re-evaluation of the way software is createdThe quality of the source code is much more important than you may thinkJust because customers don't see code doesn't mean we are excused from the effort needed to be ready for changes by keeping quality up, complexity down, and full test coverage.

Good vs. Great; Better vs. Best

http://blog.softwareontheside.com/2010/02/good-vs-great-better-vs-best.html

Monday, April 12, 2010

metaphors... (work in progress)

Asking me to add functionality to unrefactored, untested, potentially buggy code is like.... asking a craftsman to take shortcuts in his work.

Asking me to use a tool that is unfamiliar to me and I know is inferior is like...

Sunday, April 11, 2010

Why Getters/Setters are evil

http://www.javaworld.com/cgi-bin/mailto/x_java.cgi?pagetosend=/export/home/httpd/javaworld/javaworld/jw-09-2003/jw-0905-toolbox.html&pagename=/javaworld/jw-09-2003/jw-0905-toolbox.html&pageurl=http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html&site=jw_core

Why extends is evil

Why extends is evil
Improve your code by replacing concrete base classes with interfaces

By Allen Holub, JavaWorld.com, 08/01/03


http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html



I once attended a Java user group meeting where James Gosling (Java's inventor) was the featured speaker. During the memorable Q&A session, someone asked him: "If you could do Java over again, what would you change?" "I'd leave out classes," he replied. After the laughter died down, he explained that the real problem wasn't classes per se, but rather implementation inheritance (the extends relationship). Interface inheritance (the implements relationship) is preferable. You should avoid implementation inheritance whenever possible.

Losing flexibility
locks you into specific implementations, making down-the-line changes unnecessarily difficult.

coupling—the undesirable reliance of one part of a program on another part
"the fragile base-class problem" - Base classes are considered fragile because you can modify a base class in a seemingly safe way, but this new behavior, when inherited by the derived classes, might cause the derived classes to malfunction. You can't tell whether a base-class change is safe simply by examining the base class's methods in isolation; you must look at (and test) all derived classes as well. Moreover, you must check all code that uses both base-class and derived-class objects too, since this code might also be broken by the new behavior. A simple change to a key base class can render an entire program inoperable.
A better solution to the base-class issue is encapsulating the data structure instead of using inheritance.

Frameworks
an entire class framework that depends on derivation-based customization is brittle in the extreme

most of the Agile development methodologies (such as Crystal and extreme programming) simply won't work unless the code is written in the abstract.

If you examine the Gang of Four patterns closely, you'll see that many of them provide ways to eliminate implementation inheritance in favor of interface inheritance, and that's a common characteristic of most patterns. The significant fact is the one we started with: patterns are discovered, not invented. Patterns emerge when you look at well-written, easily maintainable working code. It's telling that so much of this well-written, easily maintainable code avoids implementation inheritance at all cost.

Saturday, April 10, 2010

Domain Models

AnemicDomainModel
http://martinfowler.com/bliki/AnemicDomainModel.html
Anemic Domain Model anti-Pattern is a Domain Model that exposes only data and no logic.


An Introduction to Domain Driven Design


Counter Perspectives...


Persistence Model
http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/12/03/persistence-model-and-domain-anemia.aspx
A purposely anemic domain model - or not a domain model

Immutable objects are more efficient

Scala Creator Martin Odersky talks about immutability
http://www.artima.com/forums/flat.jsp?forum=276&thread=221233

[Stateful objects] used to be a shortcut for efficiency. You couldn't create new copies of objects because that was too expensive. But it actually has turned around, even for single-threaded code. If you change an object, modern garbage collectors have to do a thing called card marking, which is incredibly expensive. The more you change fields, particularly of old objects, your performance is going to suffer. So it turns out that it's actually better to have immutable objects.

Josh Bloch on ignoring Sun's Coding Conventions

http://web.archive.org/web/20041209210459/java.sun.com/developer/community/chat/JavaLive/2002/jl0212.html


Richard Martin: In item 29 you state that variables should be declared as close as possible to the place where they are actually used. This contradicts section 6.3 of the Java Code Conventions document which states that you should "Put declarations only at the beginning of blocks". Whilst I completely agree with your reasoning and much prefer the approach you recommend, I am confused as to the lack of a clear recommendation from Sun on this.
Josh Bloch: Bluntly put, I think the Code Conventions doc is wrong on this point. More generally, I wouldn't take that document too seriously. It is not actively maintained or used at Sun.

Four "harmful" Java idioms

http://www.javaworld.com/javaworld/jw-07-2008/jw-07-harmful-idioms.html



  • Use a naming convention to distinguish three kinds of data, not two: local variables, fields, and method arguments. (disagree)

  • Prefer the package-by-feature style over package-by-layer. (interesting idea, practical?)

  • Prefer immutable objects over JavaBeans.(agree)

  • Order items in a class in terms of decreasing scope, with private items appearing last. (interesting idea, potentially confusing)




  • Referenced

    • Code Complete by Steve McConnell
    • Martin Odersky, the principal creator of Scala
    • Josh Bloch


    Friday, April 9, 2010

    An Introduction to Domain Driven Design - Dan Haywood

    An Introduction to Domain Driven Design - Dan Haywood

    http://www.methodsandtools.com/archive/archive.php?id=97

    Testing Paths

    http://adam.goucher.ca/?p=399

    • Happy Path – These are your positive tests. They provide good data, in the correct order, on the correct screens and will likely allow you to sign off on a good proportion of your requirements.
    • Sad Path – As the name suggests, these are the opposite of happy tests. Your sad tests should cover all the validation and error handling (in all layers of your application). You are going to have to look at the code to know whether you have got all these conditions, though a coverage tool might help. Remember though, that coverage tools will tell you 100% if every line has been touched, not if every line has been touched by all ways.
    • Evil Path – This is somewhat of an extension of sad tests, but they derive from people doing bad things to your application. XSS, SQL Injection, removing JS constraints, etc. fall into this category. Try to think like both the average DefCon presenter as well as a script kiddie. While the attacked might be more sophisticated from the former, the later are far more prevalent.
    • Social Path – Things along this path are more specific and start to move away from looking at the software directly and into the larger system it is a part of. In these tests the attack vector (for lack of a better term now) is the system operator rather than the system itself. What sort of things could you get the operator to give to you that they are not supposed to, and is there a solution (hopefully a technical one, but procedural might have to do) available to address it?