-
Notifications
You must be signed in to change notification settings - Fork 0
TheTaskOfProgramming
The act of programming is to take a specification of a task, even a loosely-stated specification, and turn it into a program text that, when compiled and executed, performs the specified task.
—Richard Gabriel (https://dreamsongs.com/Files/usedsf.pdf)
If you are a programmer, you do something incredibly difficult every day. It may not be obvious to you just how difficult and daunting the task of programming really is.
Our job as programmers is to shape a SoftwareSystem's Behavior
- system: a network of interacting Components
- for convenience of representation, we assume these interactions are discretized—since the computers we're talking about are digital, this is a fine assumption.
- in a software system, the components may be people, machines, programs, organizations...
- The Behavior of a component is the set of possible message-sequences exchanged between it and its Collaborators.
- message-sequences, or Interactions, may in general be arbitrarily long
- so the behavior is an infinitely large set!
- example: pocket calculator
- if we could list out all the possible Interactions required of a component, then we could automatically generate the component's code from that list. Programming would be trivial!
- ...except that enumerating the interactions is not an efficient way to implement the system—neither for us nor for the machine.
- instead, we write code, which describes the Behavior in a compressed format.
- code can be good (tight compression that uses concepts we recognize) or bad (inefficient or illegible compression)
- code is much more comprehensible than a list of interaction-sequences.
- but it still doesn't fit in our heads (beyond 10 lines or so)
- and so we cannot directly control the code.
- There isn't a straight path that goes from desired behavior -> fully-formed design in our heads -> typing the code out, start-to-finish, with no backtracking.
- when we write code, we need to use a process which involves state: intermediate artifacts (designs, work-in-progress code, tests, etc.) that persist outside our heads.
- The process tells us what to do next given the current state of our artifacts and the desired behavior of the system.
- the process includes the tools we use to comprehend and shape the code, the way we interact with teammates, how we deploy...
- we can only directly control the process. Not the code.
- We can look at the code and use our judgements about it as inputs to the process. For example, a process may involve refactoring existing code.
- My friend who was between jobs and working on a personal software project set himself the goal of working on it 8 hours a day for a month. I said, "why not set a goal of what features you want to have implemented by the end of the month?" He replied "I can't control what features are implemented. All I can control is how I work and for how long." At that, I was enlightened.
- processes are so complex and idiosyncratic that it is hard to characterize any actual process exactly. We have theoretical descriptions of processes (XP, waterfall) but these necessarily leave out many details that are specific to the project and the people working on it.
- code constrains our choice of process.
- when the tests take 4 hours, you can't do TDD. Even when tests take 40 seconds, you can't really do TDD.
- We may choose to constrain the code to accommodate certain processes.
- if we want to do TDD, it's important to shape the code and tests so the tests don't take more than a couple seconds to run.
- anecdote about member variable prefixes in C++ being used to accommodate text editors that don't highlight member variables differently
- if we are choosing a process to work with existing code, the code constrains our choice.
- Code is not the only constraint on the process. There are also fundamental constraints on human cognition and collaboration that necessarily shape the process.
- the mythical man-month: collaboration has a cost
- doherty threshold
We can only effectively approach the programming task if we acknowledge its enormous difficulty. What I have described in this chapter is a pile-up of difficulty upon difficulty several layers deep. In the subsequent chapters I will take some steps toward resolving these difficulties.