Software Development and Professional Practice, by John Dooley, is a somewhat weird book. Dooley speaks about software development, and he says the book was based on his notes on his software development classes to college juniors. The content is valuable if you are junior, otherwise you are going to read about stuff that you already know. The book is not bad, but it’s not that useful if you are an experienced software developer…

TL;DR: don’t buy it if you are an experienced software professional.

Book on Amazon:

My personal notes


  • “The hardest single part of building a software system is deciding what to build.” (Fred Brooks)
  • Requirements: a list of stuff you have to implement to create a program. They help create programs with fewer errors and cleaner design.
  • Functional requirements: what the software is supposed to do, from the user’s perspective. The don’t care about how the software is implemented.
  • Write down what your program is supposed to do before you start coding.
  • Overview: what the program is supposed to do.
  • Scenarios: present several scenarios of usage for the client. Write them as user stories (they can be related with BDD).
  • Non-requirements: what the program will not do (at least in the release).
  • Backlog: (new) requirements scheduled for a later release.
  • Types of requirements:
    • User requirements: the details of what the user expects to see as he uses the program. It includes interaction elements.
    • Domain requirements: the hear of the application.
    • Non-functional requirements: not visible to the user, but which do affect the user experience.
    • Non-requirements: things you won’t do.
  • Analyzing the requirements
    1. Categorize
    2. Prioritize
    3. Exame: is it really necessary? Is it consistent? Is it testable? Is it doable? It it unambiguous?

Software architecture

  • “A foundation on which the rest must be built.” (Martin Fowler)
  • How’re going to build the system.
  • It’s necessary to create diagrams to expose the ideas (DFD, UML, etc).
  • Pipe and filter architecture (–>[filter]–>[filter]–>).
  • Object-oriented architecture: separation of concerns and code.
  • Client-server architecture: the client takes input and displays results, and the server processes the requests.
  • Layered approach: operating systems or communication protocols.
  • Subroutine architectural pattern: decompose a problem in smaller problems (top-down decomposition), then start coding when the solution is obvious (bottom-up).

Design principles

  • “There are three ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.” (Charles Antony Richard Hoare)
  • Layers of problems:
    • Wicked problems, upper layer. Problems outside of computer science. Ill defined and large.
    • Tame problems, lower layer. Small and well defined.
  • The design will change as you understand the problem better over time.
  • The design process:
    • Design is messy.
    • Design is about tradeoffs and priorities.
    • Design is heuristics (trial and error, loosely defined rules).
    • Designs evolve (requirements change).
  • Desirable design characteristics:
    • Fitness of purpose: it must satisfy the requirements. Don’t add new requirements: the customer will do tha for you.
    • Separation of concerns: separation of functional pieces of the design (modularity).
    • Simplicity: keep the design as simple as possible.
    • Ease of maintencance.
    • Loose coupling: more modularization, less dependencies.
    • High cohesion: loose coupling consequence, self-containment of a module (it has all data it needs).
    • Extensibilidy.
    • Portability: plataform or OS.
  • Design heuristics
    • Heuristic: proceeding to a solution by trial and error.
    • Find real world objects to model: it helps keeping the desing closer to the problem/
    • Abstraction is a key: it’s a key for managing the complexity of a large problems.
    • Information hiding is your friend: isolate data and behavior (encapsulation). Everything happens through a public interface that should not change.
    • Keep your design modular: it isolates errors and changes, and helps with extensibility and maintainability.
    • Identify the parts of your design that are likely to change.
    • Use loose coupling. Use interfaces and abstract classes.
    • Use your knapsack full of common design patterns.
    • Use diagrams as a design language.
  • Designers and creativity
    • The process of reaching the design doesn’t need to be formal (while the restrictions and constraints fo the problem may be).
      1. Understand the problem.
      2. Decompose the problem into goals and objects.
      3. Select and compose plans to solve the problem.
      4. Build a mental model of a proposed solution.
      5. Mentally execute the model and evaluate it.
      6. Implement the plans.
      7. Reflect on the design product and process.

Object-oriented analysis and design

  • Build use cases.
  • Make simple classes that work together.
  • Classes should have only one responsability.

Object-oriented design principles

  • Encapsulate things that are likely to change: abstract “immutable” behavior (methods).
  • Code to an interface (to inherit from it).
  • Open-Closed Principle (OCP): classes should be open for extension and closed for modification.
  • Don’t Repeate Yourself Principle (DRY): avoid duplicate code.
  • Single Responsability Principle (SRP): every object (class) should have a single responsability.
  • Liskov Substitution Principle (LSP): subclasses must be replaceable by their base class. A user should be able to instantiate an object as a subclass and use all the base class functionality invisibly.
  • Favour delegation, composition and aggregation over inheritance.
  • Dependence Inversion Principle (DIP): don’t depend on concrete classes, depend on abstractions.
  • Interface Segregation Principle (ISP): clients shouldn’t depend on classes (methods) they don’t use. Interfaces should be small and cohese. Instead of adding new methods to an interface, make more interfaces.
  • Principle of Least Knowledge (PLK): classes should collaborate indirectly with as few other classes as possible (loose coupling). Keep dependencies on a minimum.

Design patterns

  • Something that names, abstracts and identifies the key aspects of a common design structure that makes it useful for creating a reusable object-oriented design (e.g: GOF patterns).