0002.p Tools and collaboration
On this page
Very little software is written by one person from nothing. Programmers work with tools that help them write and inspect code, with teammates who share the same code, and with code written by people they will never meet. This section widens in those three circles. It starts with the individual programmer's workbench, the integrated development environment and its debugger. It moves to the team, where version control and a set of shared practices let several people change the same code without losing work or knowledge. And it ends with the wider world of libraries, package managers, and APIs, where reuse brings legal and ethical obligations along with technical benefits.
The programmer's workbench#
A programmer can get by with a plain text editor, a separate terminal for running programs, and print statements for finding bugs. An integrated development environment (IDE) combines these jobs in one application: an editor, a debugger, and tools to build and run programs. IDEs usually add further help, such as code completion, which suggests names as you type, background error checking, which underlines problems as code is written by running the kind of static analysis described in 0002.n, and integration with version control. Running a program and then stepping through it line by line can therefore be done in one place, without switching tools.
Some teachers and students object that an IDE hides what is happening. There is something to this, since an IDE is an abstraction over separate tools for editing, compiling or interpreting, and debugging, and those tools are still worth understanding. The reasonable position is to learn how the underlying tools work and then use an IDE for the productivity it brings, in the same way that 0002.e describes using any abstraction.
The debugger is the IDE tool most directly tied to the debugging process of 0002.n. It lets a programmer pause a program at a breakpoint, a marked line, then step through it line by line and inspect variable values, all without editing the code. To watch total change on each pass of a loop, set a breakpoint inside the loop and inspect total at each stop, where the alternative would be adding and later removing print statements. A conditional breakpoint pauses only when a stated condition is true, which is far more efficient when a bug appears for one specific input after thousands of iterations. When paused at a line that calls a function, "step into" enters the called function to follow its statements, while "step over" runs the whole call as one step and pauses at the next line. "Step out" finishes the function being run and pauses back in the code that called it, and "continue" resumes the program until the next breakpoint or the end. Interactive debugging has limits, though. An error that occurs only on a remote server in production can't easily be paused and inspected, and there, log statements that record events as the program runs are the better tool.
Working as a team#
When several people change the same code, they need a shared record of what changed, and version control provides it. A system such as Git records a project's history as a series of commits, each a recorded snapshot of the project, with a message explaining what changed and why. "Fixed stuff" is a poor message, because it tells teammates nothing they can use later. Branches let people work separately: a student who wants to try a risky change without affecting the working version can make it on a separate branch, and either keep it or discard it. Merging combines changes from different branches. Git can merge most changes automatically, but when two people have edited the same lines, it reports a merge conflict, and a person has to decide how the two changes should be combined, because the tool can't know what either person intended. History also helps with debugging. If a bug appeared at some point in the last 40 commits, testing earlier commits, which tools such as git bisect do efficiently by halving the range each time, finds the commit that introduced it.1
Version control handles the code, and a set of practices handles the people. In code review, another developer reads each change before it is merged, which catches problems and also spreads knowledge of the code across the team, so that no part of it is understood by only one person. In pair programming, two people work together on one task: a driver types while a navigator reviews and thinks ahead, and they switch roles regularly. An issue tracker keeps a shared record of bugs and tasks, so they aren't lost in scattered chat messages and emails. A style guide, often enforced by an automatic formatter, settles questions of formatting once, so that reviews can focus on logic. The interpersonal side of review matters as much as the technical side. A useful review comment is specific and respectful, as in "Could this be split into two functions? I had trouble following the second loop," which names the problem and suggests a remedy without judging the author.2
Code from outside the team#
The widest circle is code written elsewhere. A library is reusable code that a program calls instead of reimplementing, such as a library for reading CSV files. Libraries are especially valuable when a task is hard to get right and errors are costly, as with cryptography, where a well-maintained library handles difficult details that a single programmer could easily get wrong. Downloading a library's files and pasting them into a project works, but it loses track of where the code came from and which version it is. A package manager installs libraries and tracks their versions as dependencies.3 Recording exact dependency versions in a project's configuration makes environments reproducible, which prevents a program from working on one laptop and failing on a classmate's because the two have different versions of a library. It also makes upgrades easier: when a security advisory reports a flaw in a library, the package manager shows which version is installed and can upgrade it. The same record lets a project go back to an earlier version when an upgrade breaks a function the program calls, and a library may itself depend on other libraries, so installing one library can install several packages. A program run on a computer that lacks a library it calls fails with a message that the library was not found, and installing the recorded dependencies there fixes it.
Some services are reached over a network instead of installed. An application programming interface (API) defines how programs can request services or data from another system, without needing to know how that system is implemented. A weather app that sends a request for a city's forecast to a provider's published address and receives data in a documented format is using an API, though it knows nothing about how the forecast is produced.45 An API is a contract, and the interface and implementation distinction of 0002.e applies directly: if a map company changes the internal system behind its directions API but keeps the requests and responses the same, programs that use the API keep working without changes. For the same reason, a program that calls a documented API breaks less often than one that pulls data out of a web page's layout, which is meant for people and changes whenever the page is redesigned. To use an API, start with its documentation of endpoints, the addresses that accept requests, along with their parameters and responses. Relying on an API also creates a dependency on someone else's decisions. The provider controls its terms, which can change, so a program built on a free API can stop working when the provider imposes a limit of 100 requests a day.
Reusing code also brings obligations that are legal and ethical as well as technical. Responsible reuse requires understanding what the code does, following its license, and crediting its source where required. A function pasted from a forum without being read may not do what the student assumes. Licenses set the conditions of reuse, which may include attribution or sharing changes, so following the license's terms is the obligation that most often accompanies open-source code. Code with an unknown license, such as a function copied from a blog post into a commercial product, may not be legal to reuse at all, because the company may lack the right to use it. A comment that names the original project and its license both gives credit and shows that the terms are being followed. Code produced by a generative AI tool calls for the same care as any other reused code: read it and test it until you understand what it does before relying on it.
Closing the competency#
This section completes a path through computational thinking and programming. It began with models and data, moved through the core ideas of decomposition, abstraction, algorithms, and data structures, examined how algorithms are represented, evaluated, and organized into objects, and followed programs through design, testing, and refinement. The tools and practices here are where all of that meets the working world, in which programs are built by people working together and drawing on one another's code. Everything so far has treated the computer as a reliable machine that runs whatever it is given. The next competency, beginning with 0003.a, opens that machine up, looking at the hardware, software, and networks that programs run on and communicate through.
- integrated development environment (IDE): an application combining an editor, debugger, and build or run tools
- code completion: an editor feature that suggests names and code as you type
- debugger: a tool for pausing a program, stepping through it, and inspecting variables
- breakpoint: a marked line at which a debugger pauses a program
- conditional breakpoint: a breakpoint that pauses only when a condition is true
- step into / step over: entering a called function, or running the call as one step
- version control: a system, such as Git, that records a project's history
- commit: a recorded snapshot in a project's history, with a message explaining the change
- branch: a separate line of work in version control
- merge: combining changes from different branches
- merge conflict: overlapping changes that a person must resolve
- code review: reading another developer's change before it is merged
- pair programming: two people working on one task, as driver and navigator
- issue tracker: a shared record of bugs and tasks
- style guide: shared conventions for formatting and naming code
- library: reusable code that a program calls
- package manager: a tool that installs libraries and tracks their versions as dependencies
- dependency: a library or service that a program relies on
- application programming interface (API): a definition of how programs can request services or data from another system
- license: the terms under which code may be reused
Practice: practice questions for 0002.p
-
MWC1, Drawing project: planning, milestones, debugging, and version control through
mwc submit. ↩ -
MWC2, Banjo app: a teacher portal case study, including requirements, components, and FERPA. ↩
-
MWC1, Retro: a game library, its modules, and working with agents. ↩
-
MWC1, Weather: dictionaries, web APIs, and distributed services. ↩
-
MWC2, Riddles: HTTP requests, responses, verbs, and status codes. ↩