1 of 47

1

CS61B, Fall 2024 @ UC Berkeley

Industrial Applications!

Software Engineering II

Lecture 31

2 of 47

Background

Vanessa Teo (she/her)

  • Senior majoring in CS + Env Econ & Policy
  • 6th semester on staff
  • SWE & MLE @ Pinterest + Startup
  • ML Research @ Berkeley AI Research
  • Has two cats named Fish & Chips

3 of 47

Today’s lecture will be about the building a project from the ground up. The concepts we’ll discuss today can be used right now! They’ll also apply forever :)

General Q&A will be at the end.

4 of 47

Design

Lecture 31, CS61B, Fall 2024

Design

Managing Complexity

Documentation

Group Coordination

Q & A

5 of 47

Why Design?

“Instead of wasting time by designing my program, I can save time by starting to code now” - Person who will regret their decision soon™

Design is an important first stage in development:

  • Ensures consideration of all requirements and constraints
  • Considers multiple alternatives and their advantages / disadvantages
  • Identifies potential costs or pitfalls while change is cheap
  • Allows multiple minds to weigh in and leverages diverse perspectives

6 of 47

Design Documents

Design documents do not need to follow a specific form, but they should give the reader easily accessible information about your project.

A design document should:

  • Quickly bring the reader up to speed
  • Include what alternatives were considered and why the trade-offs were made
  • Be just as much about the “why” as it is about the “how”
  • Update as the project progresses (be alive!)

7 of 47

Design Documents in Industry

Often, design documents will be reviewed before work on the project even begins.

When onboarding to an existing project, the first question someone will ask is “where’s the design doc?”

Design docs are reviewed in performance reviews

8 of 47

Design in Project 3

Think about each class you want to create and how they will fit together

  • Putting everything into one file will make you sad :(
  • Ideally each class should have one role

Consider what methods are required to meet each class’s functionality

The major algorithms you’ll need to think about are room and hallway generation

You are making something new!

9 of 47

Managing Complexity

Lecture 31, CS61B, Fall 2024

Design

Managing Complexity

Documentation

Group Coordination

Q&A

10 of 47

Who Cares?

Who Cares?

  • You probably don’t want your work to end up like Space Cadet Pinball

11 of 47

Technical Debt

  • Your work will be available to other people.
    • People are going to build off of it, or at least see it.
      • Maybe this is your future self!
    • Ideally, it should be flawless and well-documented.
  • Deadlines exist.
    • School deadlines, grants, conferences, reviews, etc.
    • Prototypical, hastily-written code is inevitable.

There is pressure to achieve both quality and quantity.

This is inarguably a trade-off—prioritizing one will negatively affect the other.

This doesn’t just apply to code—it applies to life.

How do you deal with this? Strategic vs Tactical Programming

12 of 47

Tactical Programming

The focus is on getting something working quickly, leveraging workarounds.

Ex: Code that contains many nested if statements to handle many separate cases that is hard to explain.

Prototypes, proof-of-concepts leverage tactical programming. The goal is to show that something could theoretically work.

However:

  • There’s minimal time spent on overall design
  • Things are complicated with workarounds to get things working
  • Refactoring takes time and potentially means restarting
    • Consider Project 2 runtime requirements and planning the constructor
  • Often, the prototype ends up deployed in the real world due to a lack of time

13 of 47

Strategic Programming

A different form of programming that emphasizes long term strategy over quick fixes. The objective is to write code that works elegantly - at the cost of planning time.

Code should be:

  • Maintainable
  • Simple
  • Future-proof
    • 61B projects have deadlines; afterwards, you can throw it away

If the strategy is insufficient, go back to the drawing board before continuing work.

This is your design document for Project 2B.

14 of 47

Importance

  • What is “good code”? Three main goals:
    • Readability: The code is easy to read and understand.
    • Simplicity: The solution is straightforward, without unnecessary complexity
    • Testability: The code is easy to test and debug.
  • Why is good code important?
    • Facilitates easier maintenance and debugging
    • Enhances collaboration and code readability
    • Directly impacts the success and scalability of project

15 of 47

Bad Style

  • Poor and Inconsistent Formatting
    • Multiple styles mixed in the same project
    • snake_case, camelCase, SCREAMING_SNAKE_CASE, flatcase, kebob-case

  • Over-Complexity
    • simple tasks are over-complicated by unnecessary steps or �convoluted logic
    • repetitive code that re-implements the same logic

16 of 47

IMPORTANT NOTE!

Refactoring is changing your code to make things more organized without affecting functionality.

Before refactoring, always add and commit your code! This way, you can restore your old work if necessary.

17 of 47

Bad Code Example - What’s wrong with this?

static void print3DArray(String[][][] arrays) {

System.out.print("[");

for (int i = 0; i < arrays.length; i++) {

if (arrays[i] == null) {

continue;

}

System.out.print("[");

for (int j = 0; j < arrays[i].length; j++) {

if (arrays[i][j] == null) {

continue;

}

System.out.print("[");

for (int k = 0; k < arrays[i][j].length; k++) {

System.out.print(arrays[i][j][k]);

if (k < arrays[i][j].length - 1) {

System.out.print(", ");

}

}

System.out.print("]");

if (j < arrays[i].length - 1) {

System.out.print(", ");

}

}

System.out.print("]");

if (i < arrays.length - 1) {

System.out.print(", ");

}

}

System.out.print("]\n");

}

  • I have no idea what’s going on
    • Probably prints 3D arrays?

18 of 47

Bad Code Example - Test to verify correctness as you refactor

public static void main(String[] args) {

String[][][] arrays = new String[][][] {

new String[][] {

new String[] {"1", "2", "3"},

new String[] {"4", "5", "6"},

new String[] {"7", "8", "9"}

},

null,

new String[][] {

new String[] {"10", "11", "12"},

new String[] {"13", "14", "15"},

new String[] {"16", "17", "18"}

}

};

print3DArray(arrays);

}

  • Small test
    • [[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]]]
    • Hey, it works! Why change it?

19 of 47

Bad Code Example - Use the tools of the language

static void print3DArray(String[][][] arrays) {

System.out.print("[");

for (String[][] array : arrays) {

if (array == null) {

continue;

}

System.out.print("[");

for (String[] arr : array) {

if (arr == null) {

continue;

}

System.out.print("[");

for (String a : arr) {

System.out.print(a + ", ");

}

System.out.print("], ");

}

System.out.print("], ");

}

System.out.print("]\n");

}

  • Enhanced-for loops exist
  • Still bad, but much better, even with terrible variable names
    • Small test
      • [[[1, 2, 3][4, 5, 6][7, 8, 9]][[10, 11, 12][13, 14, 15][16, 17, 18]]]
      • Hey, you broke it! Change it back!

20 of 47

Bad Code Example - Separate logic into simple methods

static void print3DArray(String[][][] arrays) {

System.out.print("[");

for (String[][] array : arrays) {

print2DArray(array);

System.out.print(", ");

}

System.out.print("]\n");

}

static void print2DArray(String[][] array) {

if (array != null) {

System.out.print("[");

for (String[] arr : array) {

print1DArray(arr);

System.out.print(", ");

}

System.out.print("]");

}

}

static void print1DArray(String[] arr) {

if (arr != null) {

System.out.print("[");

for (String a : arr) {

System.out.print(a + ", ");

}

System.out.print("]");

}

}

  • Much better!
  • Our test still doesn’t work.
    • [[[1, 2, 3, ], [4, 5, 6, ], [7, 8, 9, ], ], [[10, 11, 12, ], [13, 14, 15, ], [16, 17, 18, ], ], ]
    • Weird comma behavior for the last element of arrays.
      • Notably, we have this problem for every nested array
  • We have identical print statements for the commas and square brackets everywhere, with similar issues for all of them.
    • Something like generic types would probably come in handy here, but these methods are static

21 of 47

Bad Code Example - Code generically; don’t repeat yourself

static void print3DArray(String[][][] arrays) {

printCommaSeparated(arrays);

System.out.print("\n");

}

static void print2DArray(String[][] array) {

printCommaSeparated(array);

}

static void print1DArray(String[] arr) {

printCommaSeparated(arr);

}

static <T> void printCommaSeparated(T[] arr) {

if (arr != null) {

System.out.print("[");

for (int i = 0; i < arr.length; i++) {

System.out.print(arr[i]);

if (i < arr.length - 1) {

System.out.print(", ");

}

}

System.out.print("]");

}

}

  • You actually can have generic static methods in Java.
  • [[[Ljava.lang.String;@e9e54c2, null, [[Ljava.lang.String;@65ab7765]
    • ?!

22 of 47

Bad Code Example - Don’t reinvent the wheel

static void print3DArray(String[][][] arrays) {

printCommaSeparated(arrays);

System.out.print("\n");

}

static void print2DArray(String[][] array) {

printCommaSeparated(array);

}

static void print1DArray(String[] arr) {

printCommaSeparated(arr);

}

static <T> void printCommaSeparated(T[] arr) {

if (arr != null) {

System.out.print(Arrays.toString(arr));

}

}

  • [[[Ljava.lang.String;@e9e54c2, null, [[Ljava.lang.String;@65ab7765]
    • This occurs due to the nested-ness of our problem.
    • This is actually pretty annoying to resolve - an exercise for the brave amongst you is to fix it without using the library solution.

23 of 47

Better Code Example - Cheat Don’t reinvent the wheel, again

static <T> void printArray(T[] arr) {

System.out.print(Arrays.deepToString(arr));

}

  • [[[1, 2, 3], [4, 5, 6], [7, 8, 9]], null, [[10, 11, 12], [13, 14, 15], [16, 17, 18]]]
    • Yes, we have that null in there, but it’s totally a feature, not a bug
  • This now works for any amount of nested arrays. And any (non-primitive) type of array!

24 of 47

Original vs Refactored

static void print3DArray(String[][][] arrays) {

System.out.print("[");

for (int i = 0; i < arrays.length; i++) {

if (arrays[i] == null) {

continue;

}

System.out.print("[");

for (int j = 0; j < arrays[i].length; j++) {

if (arrays[i][j] == null) {

continue;

}

System.out.print("[");

for (int k = 0; k < arrays[i][j].length; k++) {

System.out.print(arrays[i][j][k]);

if (k < arrays[i][j].length - 1) {

System.out.print(", ");

}

}

System.out.print("]");

if (j < arrays[i].length - 1) {

System.out.print(", ");

}

}

System.out.print("]");

if (i < arrays.length - 1) {

System.out.print(", ");

}

}

System.out.print("]\n");

}

static <T> void printArray(T[] arr) {

System.out.print(Arrays.deepToString(arr));

}

25 of 47

Bonus: Quake III - Fast Inverse Square Root (with original comments)

float q_rsqrt(float number)

{

long i;

float x2, y;

const float threehalfs = 1.5F;

x2 = number * 0.5F;

y = number;

i = * ( long * ) &y; // evil floating point bit level hacking

i = 0x5f3759df - ( i >> 1 ); // what the fuck?

y = * ( float * ) &i;

y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration

// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed

return y;

}

26 of 47

Good Style and Clean Code Guidelines

  • Every company has preferences, and you must follow their conventions
  • Google Style Guide
  • 61B’s Style Guide!

  • Not a complete list of guidelines!
    • Add and commit before and after a refactor
    • Understand what your code needs to do
    • Avoid unnecessarily complex ways of doing things
    • Use descriptive method and variable names, and document your code well
    • Separate logic into simpler methods
    • Don’t reinvent the wheel
    • Google and StackOverflow are your friend

27 of 47

Writing Clean Code, Summary

  • Refactoring is hard.
    • No immediate clear gains—it’s all investment in the future
    • The more that is built on top of your bad code, the worse the problem becomes
      • It’s hard to tell what’ll break, and more will break the longer you wait
    • Code cleanly from the start!

28 of 47

Documentation

Lecture 31, CS61B, Fall 2024

Design

Managing Complexity

Documentation

Group Coordination

Q&A

29 of 47

Documentation Intro

  • Documentation in technology refers to various written materials that accompany software or systems
  • It covers a broad spectrum, including:
    • Code Comments
    • API Documentation
    • User Manuals
    • Design Specifications
    • Test Documents
  • We'll concentrate on practical documentation strategies that you can directly apply to your projects today

30 of 47

Why Documentation?

"We don't have enough time”

  • Quick documentation now avoids longer explanations later

"No-one would read it anyway”

  • I highly doubt it
  • Serves as a guide for future developers and users of the code
  • Essential for maintaining and scaling projects
  • In Project 3, your partner will benefit from reading it

"The code should be self-documenting”

  • Would you rather read 100 lines of someone’s code or a short summary?
  • Documentation explains why and the context, not just how

31 of 47

Documentation Example

What can we improve about this documentation?

  • Are we moving trees? Are we moving the player?
  • Why are we including java.util.Random?
  • What are x and y?

/**

* Changes location of the trees in the world

* We use java.util.Random.

*/

public boolean movePlayer(int x, int y) {...}

32 of 47

Documentation Example

/**

* Moves the player to a specified location within the game world.

* Validates the destination and checks for bounds.

*

* @param x The x-coordinate of the destination (horizontal position).

* @param y The y-coordinate of the destination (vertical position).

* @return 'true' if the move is successful, 'false' otherwise.

* @throws OutOfBoundsException if coordinates are outside the world.

* @usage To move the player to (5, 10), call movePlayer(5, 10).

*/

public boolean movePlayer(int x, int y) {...}

33 of 47

Writing Good Git Commits

There are well-established conventions:

  • Capitalize the subject line
  • Use imperative mood in the subject line
    • If applied, this commit will <subject line here>
  • Use the body to explain what and why vs how
    • Code already says how, but we need why
    • If it is complex, add source comments
  • Limit subject line to 50 characters (soft rule)
    • Ensures that commits are readable
    • If you hard time summarizing, you might be committing too many changes at once.

Rules: https://cbea.ms/git-commit/

Example: Google Truth Library (We use for writing tests!)

34 of 47

Writing Good Git Commits

Good Commit Messages:

  • Add room generation logic
  • Fix overlapping rooms
  • Make world generation tests
  • Document world generation algorithm
  • Start persistence logic
  • Refactor persistence logic to use RandomUtils
  • Reformat game homepage text to use more whitespace
  • Rearrange buttons so OK is on the lower right
  • Revise link to update it to the new URL

35 of 47

Some Bad Commit Messages

36 of 47

Overview

Poor documentation can impact productivity in three main areas:

  • Searchability
    • Time lost in deciphering and navigating code
    • Might end up rewriting the same code multiple times
  • Onboarding
    • Everyone’s implementations are different
    • In office hours, you will be onboarding course staff to your project
    • Industry examples
  • Collaboration
    • You and a partner will be writing code that both of you should understand

37 of 47

Group Coordination

Lecture 31, CS61B, Fall 2024

Design

Managing Complexity

Documentation

Group Coordination

Q&A

38 of 47

Project 3: BYOW

Project 3 is a team project.

  • This semester, as in most of the recent past, we’re doing teams of 2.

Two main reasons:

  • Get practice working on a team.
  • Get more creativity into the project since it’s so open ended.

Ancillary reason: Also reduces programming workload per person, but the project is small enough that a single person can handle it.

39 of 47

Teamwork is Hard

In the real world, some tasks are much too large to be handled by a single person.

When faced with the same task, some teams succeed, where others may fail.

Last fall, ~9% of partnerships thought their partnership did not work well for them.

40 of 47

Strategies for Collaboration: Pair Programming

Pair programming is a technique where two programmers work on a single station

  • Driver: focus on implementation
  • Navigator: consider design, accuracy

Benefits:

  • Reduce errors
  • Improve code quality
  • Increase productivity

Tips:

  • Clearly define roles
  • Swap often (15-30 mins)

You can do this remotely too!�IntelliJ: Code With Me

VS Code: Live Share

41 of 47

Agile Methodology

Agile is a flexible and iterative process to software development that emphasizes collaboration, feedback, and small, rapid releases.

Responds to change, ensures product alignment, and reduces risk.

42 of 47

Scrum Framework

An Agile framework that organizes work into structured “sprints.”

  • Scrum Master: facilitates process, removes blockers, and supports team
  • Product Owner: represents customer, prioritizes backlog, ensures maximum delivery
  • Development Team: delivers shippable increments of the product by end of sprint

43 of 47

The Sprint Cycle

  1. Sprint Planning
  2. Discuss what to accomplish in the sprint and set clear goals and alignment within the team

  • Daily Standup
  • Brief daily meeting (~15 minutes) to share progress, challenges, blockers, and plan for the day

  • Backlog Grooming
  • Go through the backlog and edit/remove/re-prioritize tickets

  • Sprint Retrospective
  • Internal team meeting to discuss what went well, improvements, and future steps

44 of 47

Scrum in Project 3

  • 1-week sprints
  • Standup every other day, maybe ~15 min

Let’s take a look at what this schedule may look like

45 of 47

Proj3A Sprint

Wednesday 11/13

  • 2 hour design doc development
  • 30 minute sprint planning

Thursday 11/14

  • Work on Proj3A
  • Send asynchronous updates

Friday 11/15

  • 15 minute standup
  • 15 minute backlog grooming
  • 1 hour pair programming

Saturday + Sunday 11/16 - 11/17

  • Work on Proj3A
  • Send asynchronous updates

Monday 11/18

  • 1 hour group Proj3A finalization

Total

~8 hours

46 of 47

Proj3B/C Sprint

Tuesday 11/19

  • Break/buffer

Wednesday 11/20

  • 15 minute sprint retrospective
  • 15 minute sprint planning
  • 1 hour design doc update

Thursday 11/21

  • Work on Proj3B independently
  • Send asynchronous updates

Friday 11/22

  • 15 minute standup
  • Work on Proj3B

Saturday + Sunday 11/23 - 11/24

  • 15 minute Sprint backlog grooming
  • Work on Proj3C

Monday 11/25

  • Break/buffer

Tuesday 11/26

  • 1 hour Proj3B/C group Finalization

Total

~7 hours

47 of 47

Q&A

Lecture 31, CS61B, Fall 2024

Design

Managing Complexity

Documentation

Group Coordination

Q&A