The Pragmatic Programmer

  1. A Pragmatic Philosophy
    • Intro
      • think about big picture
      • context lets you know how good software needs to be
      • you work with people so communicate!
    • The cat ate my source code
      • Don’t be afraid to admit ignorance or error
      • Must actively agree to responsibility but will be held accountable
      • Should nota agree if impossible or extremely high risk
      • Provide options not just excuses
    • software entropy
      • broken window theory
      • fix something as soon as its discovered or take some action to prevent further damage
      • neglect can accelerate rot
      • if everything is pristine, others will try extremely hard to not be first one to make a mess
    • stone soup and boiled frogs
      • act as catalyst for change, there is startup inertia
      • start with something you can reasonably ask for
      • do it well and let people marvel and request for features you wanted to do anyway
      • don’t get caught up in small details and let things snowball out of control
    • good enough software
      • quality depends on requirements
      • usually better to have working version sooner and get in front of users
      • getting early feedback will allow eventual solution to be better
      • know when to stop
    • knowledge portfolio
      • invest regularly
      • diversify
      • balance conservative with high risk
      • buy low / sell high
      • rebalance
      • learn one language a year
      • read a technical book once a quarter or month
      • take classes
      • participate in user groups
      • experiment with different environments
      • process of learning expands thinking and opens new ways of doing things. cross pollination of ideas is important
      • if you don’t know something track down the answer or someone who does
      • think critically about what you read. different people have different motivations (commercial)
    • communicate
      • having best ideas doesn’t matter if you can’t communicate them
      • make sure you are getting across what you want
      • know your audience and form a strong mental picture
      • use appropriate pitch for appropriate group
      • make it look good / great content can be ruined by poor presentation
      • involve audience in early draft / process can be just as important
      • listen even if you have all the info
      • follow up with people
  2. A Pragmatic Approach
    • The Evils of Duplication
      • requirements and the world are constantly changing
      • duplication causes maintenance nightmares
      • DRY: every piece of knowledge must have a single unambiguous, authoritative representation within a system
      • If you don’t DRY, will be required to make changes in multiple places and you will forget
      • Imposed duplication
        • may have shared structure across languages / can use code generator from common meta data representation
        • documentation
      • Inadvertent Duplication
        • mistakes
        • unnormalized data
        • use calculated field if you can
        • use accessors to read or write so you can modify implementation details
      • Inpatient duplication / shortcuts make for longer delays
      • Inter-developer duplication: need strong technical lead, someone who can facilitate knowledge, make things easy to reuse
    • Orthogonality
      • represent independence / decoupling
      • changes in one module or component shouldn’t affect others
      • increased productivity because small / localized and no need to change existing code
      • promotes reuse and more functionality per unit of effort
      • isolate bad code
      • system less fragile
      • easier to design and test
      • not as tightly coupled to outside vendors or 3rd party libraries
      • non-orthogonal teams results in confusion over responsibilities
      • separate components e.g. infrastructure, db, application, etc
      • to measure: see how many people are needed when discussing a change
      • if you have to drag large parts of your system to test a component, it’s probably not decoupled
      • orthogonal systems are easier to debug, test and maintain
      • if people are struggling to make changes, time to refactor
    • Reversibility
      • usually in projects, critical decisions are not easily reversible
      • have to assume things constantly change
      • there are no final decisions / always plan for contingencies
      • try to keep architecture pliable
    • Tracer Bullets
      • Can plan and spec to death
      • try to get immediate feedback
      • provides structure, get early feedback, demo-able, feel progress
      • easy to change when small
      • working but no fully functional
    • Prototypes and post-it notes
      • try out idea without committing
      • designed to answer a few questions
      • is about learning
      • can prototype architecture on whiteboard
      • code is disposable
    • Domain Languages
      • Lets you program closer to problem domain
      • data language produces some data structure
      • imperative language is executed
      • simple language might be easier to write but less flexible
      • language with more complex grammar harder to implement but more extendable and easier for people to understand
    • Estimating
      • can give you an idea of feasibility
      • context matters for accuracy
      • break models into components and understand critical components
      • run multiple cases and get ranges
      • make iterations a formal part of estimates. If you don’t and try to do everything up front, you are guessing
  3. Basic Tools
    • Power of Plain Text
      • Knowledge is base material for programmer
      • plain text best format for storing
      • plain text is self-describing and will outlive application
      • more portable across environments
      • easier to modify, test data, and analyze diffs
      • is common standard
    • Shell Games
      • Can invoke commands for manipulating files of text
      • might be obscure and terse but powerful and concise
      • invest energy and will become more productive
    • Power Editing
      • Need to be able to modify text effortlessly
      • Better to know one editor well
      • should be configurable, extensible, programmable
      • can streamline many common operations
    • Source Code Control
      • gives you serious undo capability as well as tracking changes by who
      • can manage branches and work concurrently
      • can track in central repository
      • always use source control
      • make builds automatic and repeatable
      • can run regression tests
    • Debugging
      • Think about is as a problem solving activity
      • doesn’t matter who introduced it, it’s your problem
      • Think about what could be causing problems, may be a few steps removed from where you are observing
      • try to reproduce and figure out what is going on
      • tracing can help you step through a program
      • try rubber ducking
      • usually your application code is the issue
      • re evaluate your assumptions, don’t assume, prove correctness
      • determine why not caught earlier and think if other areas are susceptible
    • Text Manipulating
      • unix like awk or sed
      • python, perl, or ruby
    • Code Generators
      • To avoid duplication across contexts can have a language agnostic representation
      • passive: generate once
      • active: consistently reproduced from a source
  4. Pragmatic Paranoia
    • Intro
      • No one can write perfect software
      • Can waste time and resource for an impossible dream
      • pragmatic programmers don’t trust themselves either
    • Design by contract
      • define rights and responsibilities
      • pre-conditions: routine should never get called with incorrect input
      • postcondition: what routine is guaranteed to do
      • class invariants: check conditions will always be true when routine exits
      • be strict with inputs and promise as little as possible
    • Dead Programs Tell No Lies
      • things can go wrong
      • if you run into an impossible scenario exit early
    • Assertive Programming
      • Programmers often think things can’t happen
      • Use assertions to ensure they won’t
      • dev/test environments may be different from production
      • for performance, make ones affecting performance optional
    • When to use exceptions
      • can make normal flow of control more clear
      • should be rarely used
      • should be able to remove and run fine under normal circumstances
      • using for normal processing breaks encapsulation and makes more tightly coupled
    • How to balance resources
      • routine that allocates resources should free it
      • deallocate resources in opposite order in which you allocate
      • when allocating same resources, always allocate in same order to avoid deadlocks
      • write modules that provide standard allocation and deallocation facilities for structures
      • check that resources are freed appropriately
  5. Bend or Break
    • Decoupling and the law of demeter
      • should not reach into multiple classes
      • ask for what you need directly
      • call methods that belong to itself, param, obj it created
      • code is more adaptable but at cost of wrapper methods that forward requests
    • Meta programming
      • good to make systems highly configurable
      • put specifics in meta data
      • forces decoupled design
      • can even put business logic in a flexible format
    • Temporal coupling
      • sequential instructions are not always realistic
      • think about actions that can be performed in parallel
      • design for concurrency
      • results in cleaner design and interfaces
      • can keep standalone or scale up
    • It’s just a view
      • pub/sub can be used to let objects receive messages
      • mvc: model shouldn’t know about controller or view
      • can connect multiple views to a model or a common view to multiple models
    • Blackboards
      • distributed data gathering process
      • decouple objects from each other
      • removes need for multiple interfaces
      • if too complex, partition
  6. While you are coding
    • Programming by coincidence
      • need to know why code is working
      • for code others will call, hide implementation details
      • need well-specified contract
      • for routines you call, rely on doc behavior
      • if you can’t, document your assumptions
      • proceed with a plan and if you can’t tell if its circumstance assume the worst
      • test / assert your assumptions
      • all code can be replace or refactored
    • Algorithm Speed
      • estimations around time, processor and memory
      • big o notation shows how it scales as function of input
      • O(n) loops
      • O(m*n) nested
      • O(log n) binary
      • O(n log n) divide and conquer
      • O(n!) combinatorial
      • estimate and test them
      • make sure the algorithm is the bottleneck before investing precious time
    • Refactoring
      • programming is more organic like gardening vs construction
      • refactor when there is duplication, nonorthogonal design, outdated knowledge, performance
      • need to understand its about removing issues when they are small and easy to fix before blows up
      • refactor early and often
      • don’t refactor and add functionality at the same time
      • takes short deliberate steps
    • Code that’s easy to test
      • build testability into software from beginning and test each piece thoroughly
      • check 1) meets contract 2) contract is what we think it is
      • test subcomponents so you can concentrate on likely sources of problems
      • tests should be conveniently located
      • tests also act as examples of functionality
      • testing frameworks allow
        • setup/cleanup
        • selecting individual or all
        • analyzing output
        • std failure reporting
      • test window: access to logs, status or even debug control panel
      • testing is more cultural than technical
    • Evil Wizards
      • must be wary of code generators
      • need to understand what they generate
      • they become an integral part of the application and are interwoven into the functionality we write
      • must be able to maintain and adapt
  7. Before the project
    • The Requirements Pit
      • requirements may be buried in deep layers of assumptions, misconceptions, and politics
      • could require digging
      • system should be well factored to support meta data
      • work with users to think like them or become a user
      • think of use cases
      • use whatever method best communicates to your audience
      • good requirements are abstract they represent a need
      • abstractions live longer than details
      • track requirements and changes (feature creep) and who is responsible for each
      • maintain a project glossary
    • Solving Impossible Puzzles
      • understand absolute constraints vs preconceived notions
      • need to recognize the degrees of freedom you have
      • don’t think outside the box, find the box
      • don’t dismiss anything. if you are certain a path can’t be taken, prove it
      • reinterpreting requirements can make a whole set of problems go away
        • is there easier way?
        • is this the right problem?
        • why is it a problem?
        • what is making this hard?
        • does it have to be done this way?
        • does it have to be done at all?
    • Not until you’re ready
      • if you having nagging doubts about starting could be instincts telling you something is not right
      • Try prototyping
      • if you feel like you are wasting time, get started on real development
      • otherwise, you may discover a premise was wrong
    • Specification trap
      • impossible to capture every detail / nuance of a system
      • if no room in specification, implementation can’t adapt and provide inform design
      • some things are better done than described
      • main thing is the delivery of a quality system
    • Circles and arrows
      • many methodologies try to come up with a precise process
      • don’t blindly follow
      • don’t be a slave to formal methods
      • charts/diagrams are meaningless to end users
      • focus on getting them a prototype
      • formal methods encourage specialization
      • formal methods may not be dynamic
      • there are costs with adopting new tools / methods
      • evaluate each method critically and take the best from each
  8. Pragmatic Projects
    • Pragmatic teams
      • Quality is a team issue
      • no broken windows
      • make sure everyone actively monitors the environment for changes
      • team must communicate within and outside of groups / have a brand
      • avoid duplication / organize by functionality
      • automate things / appoint a tool builder
    • Ubiquitous Automation
      • don’t use manual procedures
      • use things like makefiles for compilation
      • automate builds and run full tests
      • push documentation to web automatically
    • Ruthless testing
      • test early, test often, test automatically
      • unit tests, integration tests
      • try under real world conditions and environments
      • GUI: if decoupled application logic can be tested separately
      • test tests
      • think in terms of number of states not just code coverage
      • run automatically or schedule tests if they can’t be
      • add new tests for each bug / should only find a bug once
    • It’s all writing
      • make documentation an integral part of development process
      • code comment should explain why not how
      • don’t use misleading names
      • don’t have multiple sources of truth
      • can generate other files from one
      • make things easily publishable
    • Great expectations
      • need to communicate and manage expectations
      • users should have accurate view and understanding of development process, what is possible and what they will get
      • don’t just meet expectation, go above and beyond
      • think of easy features that will delight
    • Pride and prejudice
      • don’t shirk from responsibility / accept challenges
      • sign your work / accountability / ownership
      • anonymity can breed sloppiness, mistakes, and bad code
      • stand by your work
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s