Software Engineering Lab 3
Clean code
1
Content
● Writing clean code in SEL3
● Scrum & communicating about project progress
2
Writing clean code in SEL3
3
“Indeed, the ratio of time spent reading versus writing is well over 10 to
1. We are constantly reading old code as part of the effort to write new
code. ...[Therefore,] making it easy to read makes it easier to write.”
Robert C. Martin, Clean Code:
A Handbook of Agile Software
Craftsmanship
4
You are responsible for clean code
5
6
Use intention-revealing names
● “One difference between a smart programmer and a professional programmer is
that the professional understands that clarity is king. Professionals use their powers
for good and write code that others can understand.” (Robert C. Martin - Clean Code)
● Names are everywhere in software, better do it good
● Good naming is hard, take your time!
● Be consistent in names (e.g. fetch_data vs load_data)
7
Use intention-revealing names
int elapsedTime
vs
int elapsedTimeInHours
def next_step(time, velocity, delta)
vs
def get_next_velocity(current_time,
current_velocity,
delta_time)
class Metrics
vs
class PerformanceMetrics
8
Use intention-revealing names
list1 = []
for x in input_list:
list1.append(x.perf)
vs
performance_per_epoch = []
for metrics in metrics_per_epoch:
performance_per_epoch.append(metrics.performance)
(or, alternatively)
performance_per_epoch = [metrics.performance for metrics in metrics_per_epoch]
9
Functions
● Smaller is better
● Functions should do only one thing (this is harder than it sounds)
● Use intention-revealing names
● Don’t be afraid to use long names. A long descriptive name is better than a short
name with comment.
● Keep the number of arguments to a minimum
● Avoid flags in arguments
● “Master programmers think of systems as stories to be told rather than programs to
be written.” (Robert C. Martin)
10
Compare this code fragment with …
void SetupRobot(){
foreach (GameObject go in gameObjects){
if (go.name.Contains("robot")){
ArticulationBody[] articulations = go.GetComponents(typeof(ArticulationBody)) as ArticulationBody[];
foreach (ArticulationBody articulationBody in articulations){
ArticulationDrive xDrive = articulationBody.xDrive;
xDrive.stiffness = 10000;
articulationBody.xDrive = xDrive;
}
}
}
}
11
… this fragment
void MakeAllRobotsStiff(float stiffness){
List<GameObject> robots = GetAllRobots();
SetAllJointsToStiffness(robots, stiffness);
}
List<GameObject> GetAllRobots(){
List<GameObject> robots = new ArrayList<GameObject>();
foreach (GameObject go in gameObjects){
if (go.name.Contains("robot")){
robots.Add(go);
}
}
return robots;
}
void SetAllJointsToStiffness(List<GameObject> robots, float stiffness){
ArticulationBody[] articulationBodies = FindAllArticulations(robots)
SetStiffnessOfAllArticulations(articulationBodies)
}
void FindAllArticulations(List<GameObject> robots){
12
… (encapsulate foreach loop)}
The best comment …
Is no comment
“The proper use of comments is to compensate for our failure to express ourself in
code.” (Robert C. Martin - Clean Code)
13
What makes a bad comment
● Comments that can be removed with expressive code
● Commented-out code
○ You are using source control, don’t do this. Just delete it.
● To explain variables
● Redundant comments
# this method loads the data from the specified directory
def load_data(data_path: str):
...
14
Avoiding comments with good code
Example:
# check whether agent is done training
if agent.is_training and agent.nr_epochs > max_epochs
Vs
if agent_is_done_training(agent)
15
What makes a good comment?
● API documentation
● Physical quantities
○ E.g. float angular_velocity = 1.0f; # in [radians s^-1]
● Clarifications, hacks
● TODO’s
● Warnings
16
Follow a style guide
● Choose as a team which coding convention you will follow
○ Google has naming conventions: https://google.github.io/styleguide/
○ MS: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-
conventions
● Choose one, and be consistent
● Use code analysis tools
● Force style guide with build tools (e.g. pre-commit hooks with flake8, black, isort …)
17
Using version control systems (GIT)
● Commits are related to one piece of functionality
● .gitignore
● No data files in git
○ Trained models
○ Large datasets (pre-commit hook check-added-large-files)
● Git Large File Storage to track large files with Git, while keeping them out of your
actual repository
● Branches
○ main: deploy this
○ dev: push and merge all code here first
18
Project workflow tips
● Work on a fixed version (tag or release) of external libraries
● Follow directory standards when available
● Push stable releases to main branch, develop on develop branch
● Configuration system (txt, json, gin or other frameworks)
● Use Continuous Integration-tools (github actions, Jenkins, pre-commit, …) to enforce
build and code quality
20
Project documentation
● Documentation should flow out of the code
● Tools
○ Doxygen
○ Readthedocs
○ …
● README.md on github as entrypoint for external parties (in this case, this is us)
21
Undiscussed topics
● Exception handling
● Testing (unit and integration)
● Concurrency
● System building
● The use of null
● Language-specific best practices
22
Clean code in practice
To write clean code,
you first write dirty and
then clean up.
23
Scrum in SEL3
24
Scrum in SEL3
● Weekly sprints
● Scrum & consult session every week
● Questions
○ What have you done?
○ Where are you stuck?
○ What will you do the next week?
● Use any communication medium you want or need
25
Communication
26
Communication
27
What to do if you have (technical) questions?
1. LMGTFY
2. GitHub docs & issue tracker
3. Ufora & speak to each other
4. Consult sessions
5. [email protected] (start subject line with ‘[SEL3]’)
28