CS61B, 2021
Note: This lecture was lecture 34 in Spring 2019! The online video will have the wrong lecture number as a result.
Lecture 31: Software Engineering II ¡ñ Teamwork
¡ñ Cast Study in Complexity: Build Your Own World
¡ñ Modular Design
datastructur.es
Build Your Own World
datastructur.es
Build Your Own World
In the previous software engineering lecture, we talked about complexity.
¡ñ ¡°Complexity is anything related to the structure of a software system that makes it hard to understand and modify the system.¡±
¡ñ None of the assignments in 61B have really given you enough room to create truly complex code.
¡ð Project 3 will give you a chance.
In Project 3, you¡¯ll be building a system in two phases:
¡ñ World Generation ¡ñ Interactivity
datastructur.es
Part 1: World Generation
Given a random seed (long), generate a 2D world (TetTile[][]) with rooms and hallways.
¡ñ N: Create new world.
¡ñ 343434: Random seed.
¡ñ S: End of seed marker.
interactWithInputString(¡°N343434S¡±)
datastructur.es
Part 2: Interactivity
In part 2, you¡¯ll add:
¡ñ An interactive keyboard mode.
interactWithKeyboard()
User types ¡°N343434S¡±
datastructur.es
Part 2: Interactivity
In part 2, you¡¯ll add:
¡ñ An interactive keyboard mode.
¡ñ The ability for the avatar to move around in the world.
User types ¡°dddd¡±. Avatar moves four spaces east.
datastructur.es
Part 2: Interactivity
In part 2, you¡¯ll add:
¡ñ An interactive keyboard mode.
¡ñ The ability for the avatar to move around in the world.
¡ð Must also be able to handle movements given via interactWithInputString.
Let¡¯s see an actual example where complexity got out of hand due to tactical programming.
interactWithInputString(¡°N343434SDDDD¡±)
datastructur.es
The End Result of Tactical Programming
What is ¡°complex¡± about this code?
datastructur.es
The End Result of Tactical Programming
What is ¡°complex¡± about this code?
¡ñ It¡¯s repetitive.
¡ñ You can see everything that¡¯s happening on a low level.
¡ñ It is very hard to change the code if you find a problem.
datastructur.es
The End Result of Tactical Programming
What is ¡°complex¡± about this code?
¡ñ Feels a little funny to have this same constant hard coded in so many places.
¡ñ The conditionals are long and hard to read.
¡ñ There¡¯s no commenting — which isn¡¯t always a problem, but it is here maybe.
datastructur.es
The End Result of Tactical Programming
What is ¡°complex¡± about this code?
¡ñ Writing everything at a low level makes it very hard to spot errors and debug it. One approach is assigning intermediate calculations to named variables.
¡ñ Not very extensible, if things other than WALLS can block you, need more cases.
datastructur.es
The End Result of Tactical Programming
What is ¡°complex¡± about this code?
¡ñ Complex manual computation of west, east, north, and south.
¡ñ Lots of variables that need to be manipulated exactly so.
¡ñ Repetitive code (steps += 1, setting equal to PLAYER and FLOOR).
datastructur.es
Strategic Programming
Give some examples of changes you¡¯d make to simplify this code.
datastructur.es
Strategic Programming
Give some examples of changes you¡¯d make to simplify this code.
¡ñ Above all this code, have a single quartet of if statements that results in an targetX and targetY, and we use those variables just once.
¡ñ Method that help: occupied(WEST, here)
datastructur.es
Strategic Programming
Give some examples of changes you¡¯d make to simplify this code.
¡ñ Avoid having the = PLAYER, = FLOOR in all statements, instead just do them after the loop.
¡ñ Instead of four if statements, create a function that computes EAST, WEST, UP, DOWN….
datastructur.es
Strategic Programming
Give some examples of changes you¡¯d make to simplify this code. ¡ñ movePlayer(WEST)
datastructur.es
Strategic Programming
Give some examples of changes you¡¯d make to simplify this code.
¡ñ move.equals(¡°a¡±) could simply set a variable equal to ¡°WEST¡±, ¡°EAST¡±, …
¡ñ TETile getNeighbor(¡°WEST¡±) would return tile to the west.
¡ñ void move(player, world, ¡°WEST¡±) could move player tile to the west.
datastructur.es
Ousterhout¡¯s Take on Complexity
There are two primary sources of complexity:
¡ñ Dependencies: When a piece of code cannot be read, understood, and modified independently.
¡ñ Obscurity: When important information is not obvious. Both of these happen in the code we just saw.
¡ñ You must remain vigilant to remain letting dependencies and obscurities from infesting your code.
datastructur.es
The End Result of Tactical Programming
What is ¡°complex¡± about this code?
¡ñ Complex manual computation of west, east, north, and south.
¡ñ Lots of variables that need to be manipulated exactly so.
¡ñ Repetitive code (steps += 1, similar logic in many places).
obscurity! dependencies!
datastructur.es
Another Example of Complexity
As mentioned earlier, in part 2, you¡¯ll add:
¡ñ An interactive keyboard mode.
¡ñ The ability for the avatar to move around in the world.
¡ð Must also be able to handle movements given via interactWithInputString as well as interactWithKeyboard.
Handling these two different sources of input in a non-complex way is tricky.
datastructur.es
More Tactical Programming
In the solution below, interactWithKeyboard calls moveKeyboard, and interactWithInputString calls moveChar.
datastructur.es
More Tactical Programming
How could we simplify this code?
datastructur.es
More Tactical Programming
How could we simplify this code?
¡ñ Take core logic and put it in a function that is shared.
¡ñ Have first one call the second one, pass the character.
datastructur.es
More Tactical Programming
How could we simplify this code?
¡ñ Make character some default value, check when the function is run, if is null, then request a character from keyboard.
datastructur.es
More Tactical Programming
How could we simplify this code?
¡ñ Put all move input into ONE place. So, have one source of input. ¡ð Using interface inheritance / dynamic method selection.
datastructur.es
More Tactical Programming
How could we simplify this code?
¡ñ My suggestion: Create an interface called InputDevice with a nextChar() method, and pass an InputDevice as an argument to the method.
¡ð Means you only need one move method that handles any InputDevice.
datastructur.es
Don¡¯t Be This Dog
datastructur.es
Modular Design
Inspired partially by ¡°A Philosophy of Software Design¡± chapters 4 and 5.
datastructur.es
Hiding Complexity
One powerful tool for managing complexity is to design your system so that programmer is only thinking about some of the complexity at once.
¡ñ By using helper methods (i.e. getNeighbor(WEST)) and helper classes (InputDevice), you can hide complexity.
datastructur.es
Modular Design
In an ideal world, system would be broken down into modules, where every module would be totally independent.
¡ñ Here, ¡°module¡± is an informal term referring to a class, a package, or other unit of code.
¡ñ Not possible for modules to be entirely independent, because code from each module has to call other modules.
¡ð e.g. need to know signature of methods to call them.
In modular design, our goal is to minimize dependencies between modules.
datastructur.es
Interface vs. Implementation
As we¡¯ve seen, there is an important distinction between Interface and Implementation.
¡ñ Map is an interface.
¡ñ HashMap, TreeMap, etc. are implementations.
ListOfSetsDS QuickFindDS QuickUnionDS
DisjointSets
WeightedQuick
UnionDS
datastructur.es
Interface vs. Implementation
Ousterhout: ¡°The best modules are those whose interfaces are much simpler than their implementation.¡± Why?
¡ñ A simple interface minimizes the complexity the module can cause elsewhere. If you only have a getNext() method, that¡¯s all someone can do.
¡ñ If a module¡¯s interface is simple, we can change an implementation of that module without affecting the interface.
¡ð Silly example: If List had an arraySize method, this would mean you¡¯d be stuck only being able to build array based lists.
datastructur.es
Interface
A Java interface has both a formal and an informal part:
¡ñ Formal: The list of method signatures.
¡ñ Informal: Rules for using the interface that are not enforced by the
compiler.
¡ð Example: If your iterator requires hasNext to be called before next in
order to work properly, that is an informal part of the interface.
¡ð Example: If your add method throws an exception on null inputs, that is
an informal part of the interface.
¡ð Example: Runtime for a specific method, e.g. add in ArrayList.
¡ð Can only be specified in comments.
Be wary of the informal rules of your modules as you build project 3.
datastructur.es
Modules Should Be Deep
Ousterhout: ¡°The best modules are those that provide powerful functionality yet have simple interfaces. I use the term deep to describe such modules.¡±
For example, a RedBlackBSTSet 2b is a deep module.
¡ñ Simple interface:
¡ð Add, contains, delete methods.
¡ð Nothing informal that user needs to know (e.g. user doesn¡¯t have to
specify or know which nodes are red or black).
¡ñ Powerful functionality:
¡ð Operations are efficient.
¡ð Tree balance is maintained using sophisticated, subtle rules.
datastructur.es
Information Hiding
The most important way to make your modules deep is to practice ¡°information hiding¡±.
¡ñ Embed knowledge and design decision in the module itself, without exposing them to the outside world.
Reduces complexity in two ways:
¡ñ Simplifies interface.
¡ñ Makes it easier to modify the system.
datastructur.es
Information Leakage
The opposite of information hiding is information leakage.
¡ñ Occurs when design decision is reflected in multiple modules. ¡ð Any change to one requires a change to all.
¡ñ Example: Code from before. Two move methods exist that process input in very similar ways.
¡ð Information is embodied in two places, i.e. it has ¡°leaked¡±.
datastructur.es
Information Leakage
Ousterhout:
¡ñ ¡°Information leakage is one of the most important red flags in software design.¡±
¡ñ ¡°One of the best skills you can learn as a software designer is a high level of sensitivity to information leakage.¡±
datastructur.es
Temporal Decomposition
One of the biggest causes of information leakage, especially on BYOW, is ¡°temporal decomposition.¡±
In temporal decomposition, the structure of your system reflects the order in which events occur.
datastructur.es
Common Bad Pattern in BYOW
Many students do something like this:
¡ñ Game is started with an input string, so call interactWithInputString.
¡ð Parse the string and find the seed by extracting N#####S.
¡ð Generate the world.
¡ð Process each character using move(World, char).
¡ð…
¡ñ Game is started with no input string, so call interactWithKeyboard.
¡ð Display a menu and collect the seed.
¡ð Generate the world.
¡ð Until done, call moveWithKeyboard(World).
¡ð …
Example, code that collects and extracts the seed should be shared.
Temporal decomposition leads to leaking information all over the place!
datastructur.es
Summary and BYOW Suggestions
Some suggestions as you embark on BYOW:
¡ñ Build classes that provide functionality needed in many places in your code.
¡ñ Create ¡°deep modules¡±, e.g. classes with simple interfaces that do
complicated things.
¡ñ Avoid over-reliance on ¡°temporal decomposition¡± where your
decomposition is driven primarily by the order in which things occur.
¡ð It¡¯s OK to use some temporal decomposition, but try to fix any
information leakage that occurs!
¡ñ Be strategic, not tactical.
¡ñ Most importantly: Hide information from yourself when unneeded!
datastructur.es
Teamwork
datastructur.es
Project 3
Project 3 is a team project.
¡ñ This semester, 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.
Some material for this section of lecture drawn from www.teamingxdesign.com.
datastructur.es
Teamwork is Hard
History of the software engineering project in 61B:
¡ñ 2015: Gitlet (solo)
¡ñ 2016: Editor (solo)
¡ñ 2017: Databases (partner)
¡ñ 2018: Build Your Own World (partner)
When I moved from solo to partner, I thought life would be strictly easier.
¡ñ In fact, 8% of 2017 partners were unhappy with their partnership!
datastructur.es
Teamwork
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.
datastructur.es
Individual Intelligence
In 1904, Spearman very famously demonstrated the existence of an ¡°intelligence¡± factor in humans. As described in Woolley (2010):
¡ñ ¡°People who do well on one mental task tend to do well on most others, despite large variations in the tests¡¯ contents and methods of administration.¡± This mysterious factor is called ¡°intelligence.¡±
¡ñ Intelligence can be quickly measured (less than an hour).
¡ñ Intelligence reliably predicts important life outcomes over a long period of
time, including:
¡ð Grades in school.
¡ð Success in occupations.
¡ð Even life expectancy.
Note: There is nothing in Spearman¡¯s work that says that this factor is genetic.
datastructur.es
Group Intelligence
In the famous ¡°Evidence for a Collective Intelligence Factor in the Performance of Human Groups¡±, Woolley et. al investigated the success of teams of humans on various tasks.
They found that performance on a wide variety of tasks is correlated, i.e. groups that do well on any specific task tend to do very well on the others.
¡ñ This suggests that groups do have ¡°group intelligence¡± analogous to individual intelligence as demonstrated by Spearman.
datastructur.es
Group Intelligence
In the famous ¡°Evidence for a Collective Intelligence Factor in the Performance of Human Groups¡±, Woolley et. al investigated the success of teams of humans on various tasks.
Studying individual group members, Woolley et. al found that:
¡ñ Collective intelligence is not significantly correlated with average or max intelligence of each group.
¡ñ Instead, collective intelligence was correlated with three things:
¡ð Average social sensitivity of group members as measured using the
¡°Reading the Mind in the Eyes Test¡± (this is really interesting).
datastructur.es
Group Intelligence
In the famous ¡°Evidence for a Collective Intelligence Factor in the Performance of Human Groups¡±, Woolley et. al investigated the success of teams of humans on various tasks.
Studying individual group members, Woolley et. al found that:
¡ñ Collective intelligence is not significantly correlated with average or max intelligence of each group.
¡ñ Instead, collective intelligence was correlated with three things:
¡ð Average social sensitivity of group members as measured using the
¡°Reading the Mind in the Eyes Test¡± (this is really interesting).
¡ð How equally distributed the group was in conversational turn-taking,
e.g. groups where one person dominated did poorly.
datastructur.es
Group Intelligence
In the famous ¡°Evidence for a Collective Intelligence Factor in the Performance of Human Groups¡±, Woolley et. al investigated the success of teams of humans on various tasks.
Studying individual group members, Woolley et. al found that:
¡ñ Collective intelligence is not significantly correlated with average or max intelligence of each group.
¡ñ Instead, collective intelligence was correlated with three things:
¡ð Average social sensitivity of group members as measured using the
¡°Reading the Mind in the Eyes Test¡± (this is really interesting).
¡ð How equally distributed the group was in conversational turn-taking,
e.g. groups where one person dominated did poorly.
¡ð Percentage of females in the group (paper suggests this is due to
correlation with greater social sensitivity).
datastructur.es
Teamwork and Project 3
Presumably, learning habits that lead to greater group intelligence is possible. ¡ñ We hope that project 3 helps with this.
Recognize that teamwork is also about relationships!
¡ñ Treat each other with respect.
¡ñ Be open and honest with each other.
¡ñ Make sure to set clear expectations.
¡ñ … and if those expectations are not met, confront this fact head on.
datastructur.es
Reflexivity
Important part of teamwork is ¡°reflexivity¡±.
¡ñ ¡°A group¡¯s ability to collectively reflect upon team objectives, strategies, and processes, and to adapt to them accordingly.¡±
¡ñ Recommended that you ¡°cultivate a collaborative environment in which giving and receiving feedback on an ongoing basis is seen as a mechanism for reflection and learning.¡±
¡ð It¡¯s OK and even expected for you and your partner to be a bit unevenly matched in terms of programming ability.
You might find this description of best practices for team feedback useful, though it¡¯s targeted more towards larger team projects.
¡ñ Some key ideas from this document follow.
datastructur.es
Feedback is Hard: Negativity
Most of us have received feedback from someone which felt judgmental or in bad faith.
¡ñ Thus, we¡¯re afraid to give even constructive negative feedback for fear that our feedback will be misconstrued as an attack.
¡ñ And we¡¯re conditioned to watch out for negative feedback that is ill-intentioned.
Do you have any examples?
¡ñ If you have feedback that is not actually actionable, it feels bad.
¡ñ In high school: Offended every time someone would edit my essays — put
lots of work, and felt like the person giving feedback was saying you didn¡¯t
work hard enough.
¡ñ Advisors said I am not making enough progress fast enough. Think I should
datastructur.es
have more work done every week.
Feedback is Hard: Can Seem Like a Waste of Time
Feedback also can feel like a waste of time:
¡ñ You may find it a pointless exercise to rate each other twice during the project. What does that have to do with a programming class?
¡ñ In the real world, the same thing happens. Your team has limited time to figure out ¡°what¡± to do, so why stop and waste time reflecting on ¡°how¡± you¡¯re working together?
datastructur.es
Feedback is Hard: Coming Up With Feedback is Tough
Feedback can simply be difficult to produce.
¡ñ You may build incredible technical skills, but learning to provide useful feedback is hard!
¡ñ Without confidence in ability to provide feedback, you may wait until you are forced to do so by annual reviews or other structured time to provide it.
¡ð If you feel like your partnership could be better, try to talk about it without waiting until you have to review each other at the end of next week.
datastructur.es
Team Reflection
We are going to have you reflect on your team¡¯s success twice:
¡ñ This partnership has worked well for me.
¡ñ This partnership has worked well for my partner.
¡ñ Estimate the balance of work between you and your partner, briefly explain.
¡ð 50/50 means you estimate you each contributed about equally.
¡ð Note, contributing does not mean lines of code. We mean contribution in
a more general sense.
¡ñ If applicable, give a particularly great moment from your partnership.
¡ñ What¡¯s something you could do better?
¡ñ What¡¯s something your partner could do better?
Note: Except in extreme cases, we will not be penalizing partners who contributed
less!
datastructur.es