Search This Blog

Monday, February 15, 2010

Favorite Pragmatic Software Development Tips

From The Pragmatic Programmer: From Journeyman to MasterThe Pragmatic Programmer: From Journeyman to Master
See them all here.
  • DRY—Don’t Repeat Yourself
  • Always Use Source Code Control
  • Write Code That Writes Code
  • Design with Contracts
  • Refactor Early, Refactor Often
  • Abstractions Live Longer than Details
  • Don’t Use Manual Procedures
  • Test Early. Test Often. Test Automatically.
  • Use Exceptions for Exceptional Problems
  • Minimize Coupling Between Modules
  • Put Abstractions in Code, Details in Metadata
  • Design Using Services
  • Separate Views from Models
  • Don’t Program by Coincidence
  • Test Your Estimates
  • Design to Test
  • Find Bugs Once
  • Build Documentation In, Don’t Bolt It On

Sunday, February 14, 2010

First Code Smells, now Build Smells

Continuous Integration: Improving Software Quality and Reducing RiskRemove the smell from your build scripts
  • IDE-only builds
  • Copy-and-paste scripting
  • Long targets
  • Large build files
  • Failing to clean up
  • Hard-coded values
  • Builds that succeed when tests fail
  • Magic machines
  • A lack of style

Agile Modeling Best Practices

From Scott Ambler
  • Active Stakeholder Participation
  • Architecture Envisioning. At the beginning of an agile project you will need to do some initial, high-level architectural modeling to identify a viable technical strategy for your solution.
  • Document Late
  • Executable Specifications
  • Iteration Modeling
  • Just Barely Good Enough (JBGE) artifacts
  • Model a bit Ahead
  • Model Storming
  • Multiple Models
  • Prioritized Requirements
  • Requirements Envisioning
  • Single Source Information
  • Test-Driven Design (TDD)

Antipatterns (collected from wikipedia)

Antipatterns (retrieved 2-14-10). Also see programming bugs.
Organizational anti-patterns
  • Analysis paralysis: Devoting disproportionate effort to the analysis phase of a project
  • Cash cow: A profitable legacy product that often leads to complacency about new products
  • Design by committee: The result of having many contributors to a design, but no unifying vision
  • Escalation of commitment: Failing to revoke a decision when it proves wrong
  • Management by perkele: Authoritarian style of management with no tolerance for dissent
  • Moral hazard: Insulating a decision-maker from the consequences of his or her decision.
  • Mushroom management: Keeping employees uninformed and misinformed (kept in the dark and fed manure)
  • Stovepipe or Silos: A structure that supports mostly up-down flow of data but inhibits cross organizational communication
  • Vendor lock-in: Making a system excessively dependent on an externally supplied component

Project management anti-patterns
  • Death march: Everyone knows that the project is going to be a disaster – except the CEO. However, the truth remains hidden and the project is artificially kept alive until the Day Zero finally comes ("Big Bang"). Alternative definition: Employees are pressured to work late nights and weekends on a project with an unreasonable deadline.
  • Groupthink: During groupthink, members of the group avoid promoting viewpoints outside the comfort zone of consensus thinking.
  • Smoke and mirrors: Demonstrating how unimplemented functions will appear
  • Software bloat: Allowing successive versions of a system to demand ever more resources

Analysis anti-patterns
  • Bystander apathy: When a requirement or design decision is wrong, but the people who notice this do nothing because it affects a larger number of people.

Software design anti-patterns
  • Abstraction inversion: Not exposing implemented functionality required by users, so that they re-implement it using higher level functions
  • Ambiguous viewpoint: Presenting a model (usually OOAD) without specifying its viewpoint
  • Big ball of mud: A system with no recognizable structure
  • Database-as-IPC: Using a database as the message queue for routine interprocess communication where a much more lightweight mechanism would be suitable
  • Gas factory: An unnecessarily complex design
  • Gold plating: Continuing to work on a task or project well past the point at which extra effort is adding value
  • Inner-platform effect: A system so customizable as to become a poor replica of the software development platform
  • Input kludge: Failing to specify and implement handling of possibly invalid input
  • Interface bloat: Making an interface so powerful that it is extremely difficult to implement
  • Magic pushbutton: Coding implementation logic directly within interface code, without using abstraction.
  • Race hazard: Failing to see the consequence of different orders of events
  • Stovepipe system: A barely maintainable assemblage of ill-related components

Object-oriented design anti-patterns
  • Anemic Domain Model: The use of domain model without any business logic which is not OOP because each object should have both attributes and behaviors
  • BaseBean: Inheriting functionality from a utility class rather than delegating to it
  • Call super: Requiring subclasses to call a superclass's overridden method
  • Circle-ellipse problem: Subtyping variable-types on the basis of value-subtypes
  • Circular dependency: Introducing unnecessary direct or indirect mutual dependencies between objects or software modules
  • Constant interface: Using interfaces to define constants
  • God object: Concentrating too many functions in a single part of the design (class)
  • Object cesspool: Reusing objects whose state does not conform to the (possibly implicit) contract for re-use
  • Object orgy: Failing to properly encapsulate objects permitting unrestricted access to their internals
  • Poltergeists: Objects whose sole purpose is to pass information to another object
  • Sequential coupling: A class that requires its methods to be called in a particular order
  • Yo-yo problem: A structure (e.g., of inheritance) that is hard to understand due to excessive fragmentation
Programming anti-patterns
  • Accidental complexity: Introducing unnecessary complexity into a solution
  • Action at a distance: Unexpected interaction between widely separated parts of a system
  • Blind faith: Lack of checking of (a) the correctness of a bug fix or (b) the result of a subroutine
  • Boat anchor: Retaining a part of a system that no longer has any use
  • Busy spin: Consuming CPU while waiting for something to happen, usually by repeated checking instead of messaging
  • Caching failure: Forgetting to reset an error flag when an error has been corrected
  • Cargo cult programming: Using patterns and methods without understanding why
  • Coding by exception: Adding new code to handle each special case as it is recognized
  • Error hiding: Catching an error message before it can be shown to the user and either showing nothing or showing a meaningless message
  • Expection handling: (a portmanteau of expect and exception) Using a language's error handling system to implement normal program logic
  • Hard code: Embedding assumptions about the environment of a system in its implementation
  • Lava flow: Retaining undesirable (redundant or low-quality) code because removing it is too expensive or has unpredictable consequences[5][6]
  • Loop-switch sequence: Encoding a set of sequential steps using a loop over a switch statement
  • Magic numbers: Including unexplained numbers in algorithms
  • Magic strings: Including literal strings in code, for comparisons, as event types etc.
  • Soft code: Storing business logic in configuration files rather than source code[7]
  • Spaghetti code: Systems whose structure is barely comprehensible, especially because of misuse of code structures
Methodological anti-patterns
  • Copy and paste programming: Copying (and modifying) existing code rather than creating generic solutions
  • Golden hammer: Assuming that a favorite solution is universally applicable (See: Silver Bullet)
  • Improbability factor: Assuming that it is improbable that a known error will occur
  • Premature optimization: Coding early-on for perceived efficiency, sacrificing good design, maintainability, and sometimes even real-world efficiency
  • Programming by permutation (or "programming by accident"): Trying to approach a solution by successively modifying the code to see if it works
  • Reinventing the wheel: Failing to adopt an existing, adequate solution
  • Silver bullet: Assuming that a favorite technical solution can solve a larger process or problem
  • Tester Driven Development: Software projects in which new requirements are specified in bug reports
Configuration management anti-patterns
  • Dependency hell: Problems with versions of required products
  • DLL hell: Inadequate management of dynamic-link libraries (DLLs), specifically on Microsoft Windows
  • Extension conflict: Problems with different extensions to pre-Mac OS X versions of the Mac OS attempting to patch the same parts of the operating system
  • JAR hell: Overutilization of the multiple JAR files, usually causing versioning and location problems because of misunderstanding of the Java class loading model

Pitfalls of Modern Software Engineering

Another good list from a forthcoming book.

Managerial pitfalls
  • Using the wrong developers
  • Using the wrong metrics (or none at all)
  • Lying to yourself and others
  • Not identifying and managing risks
  • Adopting a technology or methodology without well-defined objectives
  • Misjudging relatives costs
  • Allowing new features to creep (or pour) in
  • Allowing the specification to drift or change without agreement
  • Attempting too much, too fast, too soon
  • Abandoning good software engineering practices

Political pitfalls
  • Not educating and enlisting management before the fact
  • Underestimating the resistance
  • Overselling the technology or methodology
  • Not recognizing the politics of architecture
  • Getting religious about the technology or methodology
  • Getting on the feature release treadmill
  • Betting the company on a given technology or methodology
  • Picking the wrong horse
Conceptual pitfalls
  • Adopting a new technology or methodology for the wrong reason
  • Thinking a new technology or methodology comes for free
  • Thinking a new technology or methodology will solve all your problems
  • Confusing buzzwords with concepts
  • Confusing tools with principles
  • Confusing training with skill
  • Confusing prototypes with finished products
  • Confusing approach with results
  • Asking the wrong questions

Some Programming Best Practices 2009

From Software Engineering Best Practices: Lessons from Successful Projects in the Top CompaniesSoftware Engineering Best Practices: Lessons from Successful Projects in the Top Companies.
  • Selection of programming languages to match application needs
  • Utilization of structured programming practices for procedural code
  • Selection of reusable code from certified sources, before starting to code
  • Planning for and including security topics in code, including secure languages such as E
  • Avoidance of “spaghetti bowl” code
  • Minimizing cyclomatic complexity and essential complexity
  • Including clear and relevant comments in the source code
  • Using automated static analysis tools for Java and dialects of C
  • Creating test cases before or concurrently with the code
  • Formal code inspections of all modules
  • Re-inspection of code after significant changes or updates
  • Renovating legacy code before starting major enhancements
  • Removing error-prone modules from legacy code

Agile Most Accepted Practices

(Scott Ambler survey 2009)
  • Continuous Integration
  • Daily Standup
  • TDD
  • Iteration Planning
  • Code Refactoring
  • Retrospectives
  • Pair Programming
  • Active Stakeholder Participation

Code Smells

From Martin Fowler's excellent book, Refactoring: Improving the Design of Existing CodeRefactoring: Improving the Design of Existing Code. More descriptions can be found here.

  • Duplicated Code
  • Long Method
  • Large Class
  • Long Parameter List
  • Divergent Change
  • Shotgun Surgery
  • Feature Envy
  • Data Clumps
  • Primitive Obsession
  • Switch Statements
  • Parallel Inheritance Hierarchies
  • Lazy Class
  • Speculative Generality
  • Temporary Field
  • Message Chains
  • Middle Man
  • Inappropriate Intimacy
  • Alternative Classes with Different Interfaces
  • Incomplete Library Class
  • Data Class
  • Refused Bequest
  • Comments

  • Duplicate code: identical or very similar code exists in more than one location.
  • Large method: a method, function, or procedure that has grown too large.
  • Large class: a class that has grown too large, see God object.
  • Feature envy: a class that uses methods of another class excessively.
  • Inappropriate intimacy: a class that has dependencies on implementation details of another class.
  • Refused bequest: a class that overrides a method of a base class in such a way that the contract of the base class is not honored by derived class. See Liskov substitution principle.
  • Lazy class: a class that does too little.
  • Duplicated method: a method, function, or procedure that is very similar to another.
  • Contrived Complexity: forced usage of overly complicated design patterns where simpler design would suffice.
Checkstyle, PMD and FindBugs for Java, to automatically check for certain kinds of code smells.

Antipatterns In Software Development, Software Architecture, and Project Management

A collection of bad practices from AntiPatterns: Refactoring Software, Architectures, and Projects in CrisisAntiPatterns: Refactoring Software, Architectures, and Projects in Crisis. More detail is available here.

Software Development Antipatterns
  • The Blob
  • Continuous Obsolescence
  • Lava Flow
  • Ambiguous Viewpoint
  • Functional Decomposition:
  • Poltergeists
  • Boat Anchor
  • Golden Hammer
  • Dead End
  • Spaghetti Code
  • Input Kludge
  • Walking through a Minefield
  • Cut-and-Paste Programming
  • Mushroom Management
Software Architecture Antipatterns
  • Autogenerated Stovepipe
  • Stovepipe Enterprise
  • Jumble
  • Stovepipe System
  • Cover Your Assets:
  • Vendor Lock-In
  • Wolf Ticket
  • Architecture by Implication
  • Warm Bodies
  • Design by Committee
  • Swiss Army Knife
  • Reinvent the Wheel
  • The Grand Old Duke of York
Project Management Antipatterns
  • Blowhard Jamboree
  • Analysis Paralysis
  • Viewgraph Engineering
  • Death by Planning
  • Fear of Success
  • Corncob
  • Intellectual Violence
  • Irrational Management
  • Project Mismanagement
  • Throw It over the Wall
  • Fire Drill
  • The Feud
  • E-mail Is Dangerous

OO Best Practices

  • The O/R Impedance Mismatch and Inheritance vs Relational Databases
  • (Prefer) Composition versus inheritance
  • SRP The Single Responsibility Principle A class should have one, and only one, reason to change.
  • OCP The Open Closed Principle You should be able to extend a classes behavior, without modifying it.
  • LSP The Liskov Substitution Principle Derived classes must be substitutable for their base classes.
  • DIP The Dependency Inversion Principle (aka IoC) Depend on abstractions, not on concretions.
  • ISP The Interface Segregation Principle Make fine grained interfaces that are client specific.
  • (also in clean code smells) The LawOfDemeter specifies a style guideline: "Only talk to your immediate friends." one never calls a method on an object you got from another call nor on a global object.
  • clean code (cc) Object/structure assymetry, data transfer object (DTO) active record is one example (don't put business logic in one)
  • tell, don't ask
  • Data professionals that claim that your object/component models must be driven by their data models

Miscellaneous Best Practices

  • Program to an interface, not an implementation
  • on par with DRY and KISS is YAGNI
  • You have to be constantly scanning your code and design and looking for code smells creeping in and opportunities to create abstraction that remove duplication or create greater efficiencies.
  • Eclipse errors/warnings settings: This should only be your first step, additional checks are provided by Findbugs and Checkstyles
  • tests: throttle test, smoke test
  • One of my favorite catch phrases is, "The difference between theory and practice is that, in theory, there is no difference, but, in practice, there is."
  • Refactor Mercilessly

Continuous Integration

“Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily – leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly” martinfowler.com

Steve McConnell wrote about doing this in 1996 in Daily Build and Smoke Test
  • Maintain a code repository
  • Automate the build
  • Make the build self-testing
  • Everyone commits every day
  • Every commit (to mainline) should be built
  • Keep the build fast
  • Test in a clone of the production environment
  • Make it easy to get the latest deliverables
  • Everyone can see the results of the latest build
  • Automate deployment
Benefits of CI
  • CI allows you to develop software faster, better and cheaper.
  • Faster: No integration points. Release builds become a non-event.
  • Better: Tested early and often. Consolidated metrics though a CI Server.
  • Cheaper: Identify defects earlier and fix when least costly.
  • Easily repeatable testing.
Risks Of Not Doing CI

  • Without CI the team can lack cohesion (incompatible conflicts, different libraries in use, “I thought you fixed that bug 3 months ago!”).
  • Lack of Visibility: Not knowing when a build fails or your code coverage.
  • Isolation: “It works on my machine!”.
  • Integrating late means fixing bugs late, which is costly.
CI will not work if you want to use:
  • Nightly Builds.
  • Developer Branches.
  • Scheduled Integration.
  • Building via an IDE.
To get the most out of CI
  • Commit early and commit often.
  • Never commit broken code.
  • Fix build failures immediately.
  • Ensure your builds run fast, and fail fast.
  • Avoid known CI Antipatterns below:
Continuous Integration: Improving Software Quality and Reducing Risk
Continuous Integration: Improving Software Quality and Reducing Risk
  • Infrequent check-ins, which lead to delayed integrations
  • Broken builds, which prevent teams from moving on to other tasks
  • Minimal feedback, which prevents action from occurring
  • Receiving spam feedback, which causes people to ignore messages
  • Possessing a slow machine, which delays feedback
  • Relying on a bloated build, which reduces rapid feedback
  • Waiting until the end of the day to commit changes, leading to Bottleneck Commits, which typically cause broken builds and frustrated developers
  • A build consisting of minimal automated processes, which results in builds that never fail, leading to Continuous Ignorance and delaying integration problems
  • Hindering build fixes through a preference for Scheduled Builds, rather than frequently building software with every code change
  • Believing that code Works on My Machine, only to discover problems later in other environments
  • Failing to remove old build artifacts, which leads to a Polluted Environment causing false positive and false negative error.
Here's a good article on creative alerting (e.g. SMS, blog update, a lighting orb) on automated build status.

Joe Wright on Continuous Integration

GoF Design Patterns

From the now-classic book Design Patterns: Elements of Reusable Object-Oriented SoftwareDesign Patterns: Elements of Reusable Object-Oriented Software.

Creational Patterns
  • Abstract Factory: Creates an instance of several families of classes
  • Builder: Separates object construction from its representation
  • Factory Method: Creates an instance of several derived classes
  • Prototype: A fully initialized instance to be copied or cloned
  • Singleton: A class of which only a single instance can exist
Structural Patterns:
  • Adapter: Match interfaces of different classes
  • Bridge: Separates an object’s interface from its implementation
  • Composite: A tree structure of simple and composite objects
  • Decorator: Add responsibilities to objects dynamically
  • Facade A single class that represents an entire subsystem
  • Flyweight: A fine-grained instance used for efficient sharing
  • Proxy: An object representing another object
Behavioral Patterns:
  • Chain of Resp.: A way of passing a request between a chain of objects
  • Command: Encapsulate a command request as an object
  • Interpreter: A way to include language elements in a program
  • Iterator: Sequentially access the elements of a collection
  • Mediator: Defines simplified communication between classes
  • Memento: Capture and restore an object's internal state
  • Observer: A way of notifying change to a number of classes
  • State: Alter an object's behavior when its state changes
  • Strategy: Encapsulates an algorithm inside a class
  • Template Method: Defer the exact steps of an algorithm to a subclass
  • Visitor: Defines a new operation to a class without change

Software Engineering Antipatterns From CRC Press

Antipatterns: Identification, Refactoring, and Management (Auerbach Series on Applied Software Engineering)A collection of bad practices from Antipatterns: Identification, Refactoring, and Management (Auerbach Series on Applied Software Engineering).

Management Antipatterns
  • Absentee Manager
  • All You Have is a Hammer
  • Cage Match Negotiator
  • Doppelganger
  • Fruitless Hoops
  • Golden Child
  • Headless Chicken
  • Leader Not Manager
  • Manager Not Leader
  • Managerial Cloning
  • Metric Abuse
  • Mr. Nice Guy
  • Mushroom Management
  • Plate Spinning
  • Proletariat Hero
  • Rising Upstart
  • Road to Nowhere
  • Spineless Executive
  • Three Headed Knight
  • Ultimate Weapon
  • Warm Bodies

Environmental Antipatterns
  • Ant Colony
  • Atlas Shrug
  • Autonomous Collective
  • Boiling Frog Syndrome
  • Burning Bag of Dung
  • Buzzword Mania
  • Deflated Balloon
  • Divergent Goals
  • Dogmatic about Dysfunction
  • Dunkirk Spirit
  • The Emperor’s New Clothes
  • Fairness Doctrine
  • Fools Rush In
  • Founderitis
  • French Waiter Syndrome
  • Geek Hazing
  • Institutional Mistrust
  • Kiosk City
  • Mediocracy
  • One-Eyed King
  • Orange Stand Economics
  • Pitcairn Island
  • Potemkin Village
  • Process Clash
  • Rubik’s Cube
  • Shoeless Children
  • Worshiping the Golden Calf

Software Architecture Patterns

Patterns from Pattern-Oriented Software Architecture Volume 1: A System of PatternsPattern-Oriented Software Architecture Volume 1: A System of Patterns

Architectural Patterns
  • Layers
  • Pipes and Filters
  • Blackboard
  • Distributed Systems
  • Broker
  • Interactive Systems
  • Model-View-Controller
  • Presentation-Abstraction-control
  • Adaptable Systems
  • Microkernel
  • Reflection

Design Patterns
  • Whole-Part
  • Organization of Work
  • Master-Slave
  • Access Control
  • Proxy
  • Management
  • Command Processor
  • View Handler
  • Communication
  • Forwarder-Receiver
  • Client-Dispatcher-Server
  • Publisher-Subscriber

Enterprise Design Patterns

Java Enterprise Design Patterns: Patterns in Java Volume 3 (With CD-ROM)Transaction Patterns
  • Acid Transaction
  • Composite Transaction
  • Two Phase Commit
  • Audit Trail
Distributed Architecture Patterns
  • Shared Object
  • Object Request Broker
  • Object Replication
  • Redundant Independent Objects
  • Prompt Repair
  • Mobile Agent
  • Demilitarized Zone
  • Process Pairs
Distributed Computing Patterns
  • Object Identifier
  • Registry
  • Protection Proxy
  • Publish-Subscribe
  • Retransmission
  • MailboxHeavyweight/Lightweight
  • Heartbeat
  • Connection Multiplexing
Concurrency Patterns
  • Session Object
  • Lock File
  • Static Locking Order
  • Optimistic Concurrency
  • Thread Pool
  • Ephemeral Cache Item
  • Transaction State Stack
Temporal Patterns
  • Time Server
  • Versioned Object
  • Temporal Property
Database Patterns
  • Persistence Layer
  • CRUD
  • Stale Object
  • Type Conversion
  • IsDirty
  • Lazy Retrieval