1 of 129

Laboratory 2

SSD

2 of 129

Topics:

Clean Code

  • What is clean code?
  • Why to write clean code?
  • Does it really matter?
  • How to write clean code?
    • Names
    • Functions
    • Comments
    • Formating

Refactoring

  • What is refactoring?
  • Do people really use it?
  • Refactoring examples
  • Optional
  • Switch Statements
  • IntelliJ IDEA Refactorings
    • Renaming
    • Extracting a variable / constant
    • Extracting a method
    • Important shortcuts

3 of 129

Clean code

4 of 129

Reference

Robert C Martin

5 of 129

Why do we need clean code???

6 of 129

Programmer

Chef

7 of 129

Writing code

Cooking

8 of 129

Writing code

Cooking

9 of 129

The only way to go

is to go

10 of 129

The only way to go

is to go

FAST

WELL

11 of 129

12 of 129

13 of 129

14 of 129

15 of 129

How to measure?

Code Quality

16 of 129

17 of 129

18 of 129

“Always leave the code you are editing better than you found it.”

Robert C. Martin (Uncle Bob)

RULE

19 of 129

What is Clean code?

20 of 129

21 of 129

22 of 129

23 of 129

24 of 129

25 of 129

Names

26 of 129

Names communicate

27 of 129

means what it says

says what it means!

and

28 of 129

Names - meaningful

int d;

int dd; //days past since project start

int m; //minutes

int daysRemaining;

int daysSinceProjectStart;

int elapsedMinutes;

29 of 129

Names - pronounceable

class DfKndSrv {

private String ord_num;

private int prq;

public String descOrdDet() {

return String.format("Order Number: %s, product Quantity: %s\n", ord_num, prq);

}

}

class DefaultCustomerService {

private String orderNumber;

private int productQuantity;

public String describeOrder() {

return String.format("Order Number: %s, " +

"product Quantity: %s\n",

orderNumber, productQuantity);

}

}

30 of 129

Names - avoid encodings

int i_days;

Address addressString;

//type changed but name did not!

String s_desc;

int days;

Address address;

String description;

31 of 129

Names - intent

int d;

int dd; //days past since project start

int m; //minutes

int daysRemaining;

int daysSinceProjectStart;

int elapsedMinutes;

32 of 129

Scope rule - variables

Short scoped variables should have short names:

Public scoped variables should have long, self-explanatory names:

for (String n : names) {

System.out.println(n.length() + "." + n);

}

public static final String PROJECT_PLUGINS_PATH = "path/to/plugins";

33 of 129

Scope rule - methods

Private methods should have long, descriptive names:

Public methods, oftenly used, should have short names:

private ArrayList<Person> keepOnlyOveragePeople(List<Person> people)

private Student findStudentByNameAndAgeGreaterThan25AndGenderMale(String name)

public interface ProjectRepository {

Project search(String projectID);

Project create(String projectID, String projectPath);

}

34 of 129

Parts of speech rule

Classes / Variables should be nouns:

Booleans should be predicates / adjectives:

Methods should be written like actions:

Enums should be adjectives:

public class Person { private String firstName; private int age; private Status status;}

public class Person { private boolean overage; public boolean isOverage() {return overage;}}

public Person searchByName(String name), public void createWeatherReport(City city),

public int generateRandomNumber(Range range)

enum Level { LOW, MEDIUM, HIGH }, enum ActivityStatus { ACTIVE, PASSIVE, RETIRED}

35 of 129

“Any fool can write code the computer would understand,

but it takes a good programmer to write code a human can understand.”

Martin Fowler, author of Refactoring, Improving the Design of Existing Code

36 of 129

Functions

37 of 129

Functions should be short

38 of 129

5-7

Lines of Code

39 of 129

Lost?

40 of 129

Names

41 of 129

Exactly one thing

42 of 129

Function arguments

No Arguments:

1 or 2 Args is OK

3 Arguments...

4+ Arguments...

43 of 129

No output arguments

public void computeResult(long x, long y, Result result) {

//...some code

result.setResult(x + y);

}

public Result computeResult(long x, long y) {

//...some code

return new Result(x + y);

}

44 of 129

No boolean arguments

public void doSomething(String someString, boolean up) {

//...some code

if (up) {

//...do some stuff

} else {

//...do some other stuff

}

}

2 Things!!!

45 of 129

No boolean arguments

public void doSomething(String someString, boolean up) {

//...some code

if (up) {

//...do some stuff

} else {

//...do some other stuff

}

}

public void doSomeStuff(String someString) {

//...do some stuff

}

2 Things!!!

public void doSomeOtherStuff(String someString) {

//...do some other stuff

}

46 of 129

Comments

47 of 129

Usually noisy

/**

* Gets notification.

*

* @param customer customer

* @param id notification id

* @return the notification for the given customer and notification id.

*/

Optional<NotificationModel> getNotification(CustomerModel customer, String id);

48 of 129

Crazy

// the name

public static String name;

// the address

public static Address address;

// the phone number

public static Phone phoneNumber;

49 of 129

Delete commented Code

public int getNumberOfFilesInProject(String projectID) {

return findProject(projectID)

.map(project -> project.getFiles().size())

.orElse(-1);

// Optional<Project> optionalProject = findProject(projectID);

// if(optionalProject.isPresent()) {

// Project project = optionalProject.get();

// return project.getFiles().size();

// }

//

// return -1;

}

50 of 129

Delete commented Code

public int getNumberOfFilesInProject(String projectID) {

return findProject(projectID)

.map(project -> project.getFiles().size())

.orElse(-1);

// Optional<Project> optionalProject = findProject(projectID);

// if(optionalProject.isPresent()) {

// Project project = optionalProject.get();

// return project.getFiles().size();

// }

//

// return -1;

}

51 of 129

Delete commented Code

public int getNumberOfFilesInProject(String projectID) {

return findProject(projectID)

.map(project -> project.getFiles().size())

.orElse(-1);

// Optional<Project> optionalProject = findProject(projectID);

// if(optionalProject.isPresent()) {

// Project project = optionalProject.get();

// return project.getFiles().size();

// }

//

// return -1;

}

52 of 129

Classes

53 of 129

One responsibility

54 of 129

Refactoring

55 of 129

How do you make sure you did not break anything?

56 of 129

57 of 129

58 of 129

Example

Why should we refactor?

59 of 129

public class Person {

private String firstName;

private String lastName;

private int age;

private Status status;

//constructor, getters, setters

}

public enum Status {

SINGLE,

MARRIED,

DIVORCED,

WIDOW

}

60 of 129

public class Person {

private String firstName;

private String lastName;

private int age;

private Status status;

//constructor, getters, setters

}

public enum Status {

SINGLE,

MARRIED,

DIVORCED,

WIDOW

}

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

ArrayList<Person> personList = new ArrayList<>();

ArrayList<String> stringList = new ArrayList<>();

for (Person person : people) {

int x = person.getAge();

if (x >= 18) {

personList.add(person);

}

}

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

String s1 = p.getFirstName() + " " + p.getLastName();

stringList.add(s1);

}

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

61 of 129

What does the

getPeopleNames()

method do?

public class Person {

private String firstName;

private String lastName;

private int age;

private Status status;

//constructor, getters, setters

}

public enum Status {

SINGLE,

MARRIED,

DIVORCED,

WIDOW

}

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

ArrayList<Person> personList = new ArrayList<>();

ArrayList<String> stringList = new ArrayList<>();

for (Person person : people) {

int x = person.getAge();

if (x >= 18) {

personList.add(person);

}

}

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

String s1 = p.getFirstName() + " " + p.getLastName();

stringList.add(s1);

}

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

62 of 129

63 of 129

Did you get it?

64 of 129

65 of 129

What does the

getPeopleNames()

method do?

public class Person {

private String firstName;

private String lastName;

private int age;

private Status status;

//constructor, getters, setters

}

public enum Status {

SINGLE,

MARRIED,

DIVORCED,

WIDOW

}

public class PersonService {

public List<String> getOveragePeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

List<String> overagePeopleNames = getPeopleFullNames(overagePeople);

overagePeopleNames = sortNamesAlphabetically(overagePeopleNames);

printNames(overagePeopleNames);

return overagePeopleNames;

}

...

}

66 of 129

What does the

getPeopleNames()

method do?

public class Person {

private String firstName;

private String lastName;

private int age;

private Status status;

//constructor, getters, setters

}

public enum Status {

SINGLE,

MARRIED,

DIVORCED,

WIDOW

}

public class PersonService {

public List<String> getOveragePeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

List<String> overagePeopleNames = getPeopleFullNames(overagePeople);

overagePeopleNames = sortNamesAlphabetically(overagePeopleNames);

printNames(overagePeopleNames);

return overagePeopleNames;

}

...

}

67 of 129

68 of 129

69 of 129

COD

kB

70 of 129

Rename

COD

kB

71 of 129

Renaming

Shift + F6 -> Rename Field, Variable, Method, Class, File, Package, Project

72 of 129

Extracting

Ctrl + Alt + C -> Constant

Ctrl + Alt + V -> Variable

Ctrl + Alt + F -> Field

Ctrl + Alt + M -> Method

73 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

ArrayList<Person> personList = new ArrayList<>();

ArrayList<String> stringList = new ArrayList<>();

for (Person person : people) {

int x = person.getAge();

if (x >= 18) {

personList.add(person);

}

}

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

String s1 = p.getFirstName() + " " + p.getLastName();

stringList.add(s1);

}

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

74 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

ArrayList<Person> personList = new ArrayList<>();

ArrayList<String> stringList = new ArrayList<>();

for (Person person : people) {

int x = person.getAge();

if (x >= 18) {

personList.add(person);

}

}

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

String s1 = p.getFirstName() + " " + p.getLastName();

stringList.add(s1);

}

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

75 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

ArrayList<Person> personList = new ArrayList<>();

ArrayList<String> stringList = new ArrayList<>();

for (Person person : people) {

int x = person.getAge();

if (x >= 18) {

personList.add(person);

}

}

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

String s1 = p.getFirstName() + " " + p.getLastName();

stringList.add(s1);

}

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

private ArrayList<Person> keepOnlyOveragePeople

(List<Person> people) {

ArrayList<Person> overagePeople = new ArrayList<>();

for (Person person : people) {

if (person.getAge() >= 18) {

overagePeople.add(person);

}

}

return overagePeople;

}

Ctrl + Alt + M

Extract Method

List<Person> personList =

keepOnlyOveragePeople(people);

transformed to

76 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

List<Person> personList = keepOnlyOveragePeople(people);

ArrayList<String> stringList = new ArrayList<>();

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

String s1 = p.getFirstName() + " " + p.getLastName();

stringList.add(s1);

}

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

77 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

List<Person> personList = keepOnlyOveragePeople(people);

ArrayList<String> stringList = new ArrayList<>();

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

String s1 = p.getFirstName() + " " + p.getLastName();

stringList.add(s1);

}

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

Shift + F6

Rename

List<Person> overagePeople =

keepOnlyOveragePeople(people);

renamed to

78 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

ArrayList<String> stringList = new ArrayList<>();

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

String s1 = p.getFirstName() + " " + p.getLastName();

stringList.add(s1);

}

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

79 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

ArrayList<String> stringList = new ArrayList<>();

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

String s1 = p.getFirstName() + " " + p.getLastName();

stringList.add(s1);

}

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

private ArrayList<String> getPeopleFullNames

(List<Person> overagePeople) {

ArrayList<String> stringList = new ArrayList<>();

for (Person s : overagePeople) {

stringList.add(s.getFirstName() +

" " + s.getLastName());

}

return stringList;

}

Ctrl + Alt + M

Extract Method

List<String> stringList =

getPeopleFullNames(overagePeople);

transformed to

80 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

List<Person> personList = keepOnlyOveragePeople(people);

List<String> stringList = getPeopleFullNames(overagePeople);

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

Shift + F6

Rename

List<String> overagePeopleNames =

getPeopleFullNames(overagePeople);

renamed to

81 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

List<String> overagePeopleNames =

getPeopleFullNames(overagePeople);

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

82 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

List<String> overagePeopleNames =

getPeopleFullNames(overagePeople);

for (int i = 0; i < stringList.size(); i++) {

for (int j = i; j < stringList.size(); j++) {

if (stringList.get(i).compareToIgnoreCase(stringList.get(j)) > 0) {

String aux = stringList.get(j);

stringList.set(j, stringList.get(i));

stringList.set(i, aux);

}

}

}

for (String s : stringList) System.out.println(s);

return stringList;

}

}

private List<String> sortNamesAlphabetically(List<String> names) {

List<String> sortedNames = new ArrayList<>(names);

for (int i = 0; i < sortedNames.size(); i++)

for (int j = i; j < sortedNames.size(); j++)

if (sortedNames.get(i).compareToIgnoreCase(sortedNames.get(j)) > 0) {

String aux = sortedNames.get(j);

sortedNames.set(j, sortedNames.get(i));

sortedNames.set(i, aux);

}

return sortedNames;

}

Ctrl + Alt + M

Extract Method

  • Rename
  • Other

overagePeopleNames =

sortNamesAlphabetically(overagePeopleNames);

transformed to

83 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

List<String> overagePeopleNames = getPeopleFullNames(overagePeople);

overagePeopleNames = sortNamesAlphabetically(overagePeopleNames);

for (String s : stringList) System.out.println(s);

return stringList;

}

}

84 of 129

public class Manager {

public List<String> getPeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

List<String> overagePeopleNames = getPeopleFullNames(overagePeople);

overagePeopleNames = sortNamesAlphabetically(overagePeopleNames);

for (String s : stringList) System.out.println(s);

return stringList;

}

}

private void printNames(List<String> names) {

for (String name : names)

System.out.println(name);

}

Ctrl + Alt + M

Extract Method

printNames(overagePeopleNames);

transformed to

85 of 129

public class Person {

private String firstName;

private String lastName;

private int age;

private Status status;

//constructor, getters, setters

}

public enum Status {

SINGLE,

MARRIED,

DIVORCED,

WIDOW

}

public class PersonService {

public List<String> getOveragePeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

List<String> overagePeopleNames = getPeopleFullNames(overagePeople);

overagePeopleNames = sortNamesAlphabetically(overagePeopleNames);

printNames(overagePeopleNames);

return overagePeopleNames;

}

...

}

86 of 129

87 of 129

88 of 129

private ArrayList<String> getPeopleFullNames(List<Person> overagePeople) {

ArrayList<String> stringList = new ArrayList<>();

for (Person s : overagePeople) {

stringList.add(s.getFirstName() + " " + s.getLastName());

}

return stringList;

}

89 of 129

private ArrayList<String> getPeopleFullNames(List<Person> overagePeople) {

ArrayList<String> stringList = new ArrayList<>();

for (Person s : overagePeople) {

stringList.add(s.getFirstName() + " " + s.getLastName());

}

return stringList;

}

90 of 129

private ArrayList<String> getPeopleFullNames(List<Person> overagePeople) {

ArrayList<String> stringList = new ArrayList<>();

for (Person s : overagePeople) {

stringList.add(s.getFirstName() + " " + s.getLastName());

}

return stringList;

}

Ctrl + Alt + M

Extract Method

stringList.add(getFullName(s));

becomes

private String getFullName(Person s) {

return s.getFirstName() + " " + s.getLastName();

}

91 of 129

private ArrayList<String> getPeopleFullNames(List<Person> overagePeople) {

ArrayList<String> stringList = new ArrayList<>();

for (Person s : overagePeople) {

stringList.add(s.getFirstName() + " " + s.getLastName());

}

return stringList;

}

Ctrl + Alt + M

Extract Method

stringList.add(getFullName(s));

becomes

private String getFullName(Person s) {

return s.getFirstName() + " " + s.getLastName();

}

public class Person {

private String firstName;

private String lastName;

private int age;

private Status status;

//constructor, getters, setters

String getFullName() {

return getFirstName() + " " + getLastName();

}

}

F6

Move Instance Method

stringList.add(s.getFullName());

becomes

92 of 129

public class PersonService {

public List<String> getOveragePeopleNames(List<Person> people) {

List<Person> overagePeople = keepOnlyOveragePeople(people);

List<String> overagePeopleNames = getPeopleFullNames(overagePeople);

overagePeopleNames = sortNamesAlphabetically(overagePeopleNames);

printNames(overagePeopleNames);

return overagePeopleNames;

}

...

}

public class Person {

private String firstName;

private String lastName;

private int age;

private Status status;

//constructor, getters, setters

String getFullName() {

return getFirstName() + " " + getLastName();

}

}

93 of 129

94 of 129

Null checks

95 of 129

public class Project {

private String id;

private String name;

private List<Author> authors;

private List<Commit> commits;

private List<File> files;

//constructor, getters, setters

}

public class Author {

private String name;

private String email;

private List<Commit> commits;

//constructor, getters, setters

}

public class Commit {

private String name;

private Date date;

private Author author;

//constructor, getters, setters

}

public class File {

private String path;

private String name;

private String extension;

//constructor, getters, setters

}

96 of 129

public class NoSuchProjectException extends RuntimeException {

public NoSuchProjectException(String projectID) {

super(String.format("The project with id %s " +

"does not exist!", projectID));

}

}

public interface ProjectRepository {

Project getProjectByID(String projectID);

}

public class ProjectService {

private ProjectRepository projectRepository; // setters

private Project findProject(String projectID) {

return projectRepository.getProjectByID(projectID);

}

//rest of methods...

}

97 of 129

public int getNumberOfFilesInProject

(String projectID) {

Project project = findProject(projectID);

if (project != null) {

return project.getFiles().size();

}

return -1;

}

public String getFirstAuthorNameForProject

(String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

return project.getCommits().get(0)

.getAuthor().getName();

}

public void printProjectDetails

(String projectID) {

Project project = findProject(projectID);

if (project != null) {

System.out.printf("Project ID: %s\n

Project name: %s",

project.getId(), project.getName());

}

}

public List<String> getCommitNamesForProject

(String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

List<String> commitNames = new ArrayList<>();

for (Commit commit : project.getCommits()) {

commitNames.add(commit.getName());

}

return commitNames;

}

98 of 129

public int getNumberOfFilesInProject

(String projectID) {

Project project = findProject(projectID);

if (project != null) {

return project.getFiles().size();

}

return -1;

}

public String getFirstAuthorNameForProject

(String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

return project.getCommits().get(0)

.getAuthor().getName();

}

public void printProjectDetails

(String projectID) {

Project project = findProject(projectID);

if (project != null) {

System.out.printf("Project ID: %s\n

Project name: %s",

project.getId(), project.getName());

}

}

public List<String> getCommitNamesForProject

(String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

List<String> commitNames = new ArrayList<>();

for (Commit commit : project.getCommits()) {

commitNames.add(commit.getName());

}

return commitNames;

}

99 of 129

java.util.Optional<T>

100 of 129

Optional

101 of 129

102 of 129

2 Possible States

Present

Empty (absent)

103 of 129

Basic Operations

  • isPresent() - returns true if Optional is present and false if empty
  • get() - return the wrapped Object, or throws NoSuchElementException if empty
  • orElse(T defaultObject) - returns the wrapped Object if present, or the defaultObject if empty
  • orElseThrow(Supplier <x extends Exception> supplier) - returns the wrapped Object if present, or throws Exception provided by supplier if empty
  • ifPresent(Consumer<T> consumer) - executes consumer with the wrapped Object if present

  • Optional.of(someObject) - returns an Optional wrapping someObject
  • Optional.empty() - return empty Optional
  • Optional.ofNullable(someObject) - returns Optional wrapping someObject, or empty if someObject is null

104 of 129

Basic Rules

  1. Never, ever, use null for an Optional value or return value
  2. Never use Optional.get() unless you can prove that the Optional is present
  3. Prefer alternatives to Optional.isPresent() and Optional.get()
  4. Do not overuse Optional! (don’t replace every null check with Optional)

105 of 129

Rule #1

Never, ever, use null for an Optional value or return value

public Optional<String> getSomeString() {

//...some Code

if (someCondition())

return null;

//...some Code

}

public Optional<String> getSomeString() {

//...some Code

if (someCondition())

return Optional.empty();

//...some Code

}

Optional<Integer> optionalInteger = null;

Optional<Integer> optionalInteger =

Optional.empty();

106 of 129

Rule #2

Never use Optional.get() unless you can prove that the Optional is present

public void doSomething() {

//...

Optional<String> stringOptional = getSomeOptional();

stringOptional.get();

//...

}

public void doSomething() {

//...

Optional<String> stringOptional = getSomeOptional();

if (stringOptional.isPresent()) {

stringOptional.get();

}

//...

}

107 of 129

Interested?

108 of 129

public int getNumberOfFilesInProject

(String projectID) {

Project project = findProject(projectID);

if (project != null) {

return project.getFiles().size();

}

return -1;

}

public String getFirstAuthorNameForProject

(String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

return project.getCommits().get(0)

.getAuthor().getName();

}

public void printProjectDetails

(String projectID) {

Project project = findProject(projectID);

if (project != null) {

System.out.printf("Project ID: %s\n

Project name: %s",

project.getId(), project.getName());

}

}

public List<String> getCommitNamesForProject

(String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

List<String> commitNames = new ArrayList<>();

for (Commit commit : project.getCommits()) {

commitNames.add(commit.getName());

}

return commitNames;

}

109 of 129

public int getNumberOfFilesInProject

(String projectID) {

Project project = findProject(projectID);

if (project != null) {

return project.getFiles().size();

}

return -1;

}

public String getFirstAuthorNameForProject

(String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

return project.getCommits().get(0)

.getAuthor().getName();

}

public void printProjectDetails

(String projectID) {

Project project = findProject(projectID);

if (project != null) {

System.out.printf("Project ID: %s\n

Project name: %s",

project.getId(), project.getName());

}

}

public List<String> getCommitNamesForProject

(String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

List<String> commitNames = new ArrayList<>();

for (Commit commit : project.getCommits()) {

commitNames.add(commit.getName());

}

return commitNames;

}

110 of 129

private Project findProject(String projectID) {

return projectRepository.getProjectByID(projectID);

}

Use Optional...

111 of 129

private Project findProject(String projectID) {

return projectRepository.getProjectByID(projectID);

}

private Optional<Project> findProject(String projectID) {

Project project = projectRepository.getProjectByID(projectID);

if (project == null)

return Optional.empty();

return Optional.of(project);

}

112 of 129

private Project findProject(String projectID) {

return projectRepository.getProjectByID(projectID);

}

private Optional<Project> findProject(String projectID) {

Project project = projectRepository.getProjectByID(projectID);

if (project == null)

return Optional.empty();

return Optional.of(project);

}

private Optional<Project> findProject(String projectID) {

Project project = projectRepository.getProjectByID(projectID);

return Optional.ofNullable(project);

}

113 of 129

public List<String> getCommitNamesForProject (String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

List<String> commitNames = new ArrayList<>();

for (Commit commit : project.getCommits()) {

commitNames.add(commit.getName());

}

return commitNames;

}

public List<String> getCommitNamesForProject(String projectID) {

Project project = findProject(projectID)

.orElseThrow(() -> new NoSuchProjectException(projectID));

List<String> commitNames = new ArrayList<>();

for (Commit commit : project.getCommits()) {

commitNames.add(commit.getName());

}

return commitNames;

}

114 of 129

public String getFirstAuthorNameForProject (String projectID) {

Project project = findProject(projectID);

if (project == null) {

throw new NoSuchProjectException(projectID);

}

return project.getCommits().get(0).getAuthor().getName();

}

public String getFirstAuthorNameForProject(String projectID) {

Project project = findProject(projectID)

.orElseThrow(() -> new NoSuchProjectException(projectID));

return project.getCommits().get(0).getAuthor().getName();

}

115 of 129

public void printProjectDetails (String projectID) {

Project project = findProject(projectID);

if (project != null) {

System.out.printf("Project ID: %s\n

Project name: %s",

project.getId(), project.getName());

}

}

public void printProjectDetails(String projectID) {

findProject(projectID).ifPresent(project ->

System.out.printf("Project ID: %s\n

Project name: %s",

project.getId(), project.getName()));

}

116 of 129

public int getNumberOfFilesInProject (String projectID) {

Project project = findProject(projectID);

if (project != null) {

return project.getFiles().size();

}

return -1;

}

public int getNumberOfFilesInProject(String projectID) {

Optional<Project> optionalProject = findProject(projectID);

if(optionalProject.isPresent()) {

Project project = optionalProject.get();

return project.getFiles().size();

}

return -1;

}

117 of 129

118 of 129

Really???

119 of 129

public int getNumberOfFilesInProject (String projectID) {

Project project = findProject(projectID);

if (project != null) {

return project.getFiles().size();

}

return -1;

}

public int getNumberOfFilesInProject(String projectID) {

Optional<Project> optionalProject = findProject(projectID);

if(optionalProject.isPresent()) {

Project project = optionalProject.get();

return project.getFiles().size();

}

return -1;

}

120 of 129

public int getNumberOfFilesInProject (String projectID) {

Project project = findProject(projectID);

if (project != null) {

return project.getFiles().size();

}

return -1;

}

public int getNumberOfFilesInProject(String projectID) {

Optional<Project> optionalProject = findProject(projectID);

if(optionalProject.isPresent()) {

Project project = optionalProject.get();

return project.getFiles().size();

}

return -1;

}

Rule #3

121 of 129

Rule #3

Prefer alternatives to Optional.isPresent() and Optional.get()

public void doSomething() {

//...

Optional<String> stringOptional = getSomeOptional();

if (stringOptional.isPresent()) {

stringOptional.get();

}

//...

}

122 of 129

Optional Map operation

Burger with meat

Burger with fries

Optional<M>

Optional<F>

map

123 of 129

Optional Map operation

Optional<Person>

Optional<String>

map

Optional<Person> optionalPerson = Optional.empty();

Optional<String> firstNameOptional = optionalPerson

.map(person -> person.getFirstName());

124 of 129

public int getNumberOfFilesInProject(String projectID) {

Optional<Project> optionalProject = findProject(projectID);

if(optionalProject.isPresent()) {

Project project = optionalProject.get();

return project.getFiles().size();

}

return -1;

}

public int getNumberOfFilesInProject(String projectID) {

return findProject(projectID)

.map(project -> project.getFiles().size())

.orElse(-1);

}

125 of 129

126 of 129

127 of 129

IntelliJ IDEA Refactoring Shortcuts

Shift + F6

Rename

Ctrl + Alt + C

Extract Constant

Ctrl + Alt + V

Extract Variable

Ctrl + Alt + F

Extract Field

Ctrl + Alt + M

Extract Method

Ctrl + Alt + N

Inline variable / method

Alt + Delete

Safe Delete

Ctrl + Alt + L

Reformat Code

Alt + Enter

Smart Suggestions

128 of 129

References

129 of 129

Hands-On