SlideShare a Scribd company logo
1 of 38
Download to read offline
O klasycznej programistycznej elegancji
http://my.opera.com/rato53/albums/
Jakub Marchwicki
Technical Consultant
Java, Lua, PHP
i tak od 9lat
marchwicki.pl/blog
@kubamarchwicki
Kanon piękna?
© vitra
Kanon piękna?
„Any fool can
write code that a
computer can
understand. Good
programmers
write code that
humans can
understand“
Refactoring: Improving the Design of Existing Code, 1999
Martin Fowler jeszcze raz
Joshua Bloch
Effective Java
I sure wish I had
this book ten
years ago
James Gosling
Kent Beck
„Many people
don’t realize how
readable code
can be and how
valuable that
readability is.
Kent has taught
me so...“ Martin Fowler
Implementation patterns
Communication
Simplicity
Flexibility
A wszystko dlatego że
największym kosztem
oprogramowania
będzie i tak jego
utrzymanie
Kryteria dobrego kodu
© http://www.agileadvisor.com/
private static boolean isOlderExtremeVersion(String d1, String d2) {
String[] dateOneA = dateOne.split("-");
String[] dateTwoA = dateTwo.split("-");
if ((Integer.valueOf(dateOneA[0]).intValue() >
Integer.valueOf(dateTwoA[0]).intValue())
|| (Integer.valueOf(dateOneA[0]).intValue() ==
Integer.valueOf(dateTwoA[0]).intValue()
&& Integer.valueOf(dateOneA[1]).intValue() >
Integer.valueOf(dateTwoA[1]).intValue())
|| (Integer.valueOf(dateOneA[0]).intValue() ==
Integer.valueOf(dateTwoA[0]).intValue()
&& Integer.valueOf(dateOneA[1]).intValue() ==
Integer.valueOf(dateTwoA[1]).intValue()
&& Integer.valueOf(dateOneA[2]).intValue() >
Integer.valueOf(dateTwoA[2]).intValue())) {
return false;
}
return true;
}
Nie będzie Eclipsa...
public class Person {
private String firstName;
private String lastName;
private long birthDate;
}
public class Student extends Person {
private int year;
}
public class Professor extends Person {
private String[] specjalities;
}
public class Lecture {
private String title;
private Professor professor;
private Student[] students;
}
Wyobraźmy sobie model...
public boolean equals(Object o) {
if (!(o instanceof Person))
return false;
final Person p = (Person) o;
return firstName.equals(p.firstName)
&& lastName.equals(p.lastName)
&& birthDate == p.birthDate;
}
public int hashcode() {
int result = 17;
result = 37*result + firstName.hashCode();
result = 37*result + lastName.hashCode();
result = 37*result + (int)(birthDate ^ birthDate >>> 32);
return result;
}
A teraz piszemy...
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(specjalities);
return result;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof Professor)) {
return false;
}
Professor other = (Professor) obj;
if (!Arrays.equals(specjalities, other.specjalities)) {
return false;
}
return true;
}
lub generujemy...
public String toString() {
return "Professor [specjalities=" +
Arrays.toString(specjalities) + "]";
}
to samo tyczy się toString()'a
public boolean equals(Object o) {
if (o == null) { return false; }
if (o == this) { return true; }
if (o.getClass() != getClass()) { return false; }
final Student s = (Student) o;
return new EqualsBuilder()
.appendSuper(super.equals(o)).append(year, s.year)
.isEquals();
}
public int hashcode() {
return new HashCodeBuilder(17, 37)
.appendSuper(super.hashcode()).append(year)
.toHashCode();
}
public String toString() {
return new ToStringBuilder(this)
.appendSuper(super.toString()).append("year", year)
.toString();
}
ale przy setce encji się nie chcieć
public boolean equals(Object o) {
if (o instanceof Lecture) {
Lecture l = (Lecture) o;
return Objects.equal(professor, l.professor)
&& Objects.equal(students, l.students)
&& Objects.equal(title, l.title);
}
return false;
}
public int hashcode() {
return Objects.hashCode(title, professor, students);
}
public String toString() {
return Objects.toStringHelper(this)
.add("professor", professor)
.add("students", students)
.toString();
}
albo mniej fundamentalnie
public void addLectureWithCommons(Lecture lecture, Venue venue,
int dayOfTheWeek, int hour) {
Validate.isTrue(dayOfTheWeek > 0 && dayOfTheWeek <= 7,
"There are only 7 days of the week");
Validate.isTrue(hour >= 0 && hour < 23, "Day has only 24hours");
Validate.notNull(lecture != null, "Lecture cannot be null");
Validate.notNull(venue != null, "Venue cannot be null");
// reminder omitted
}
public void addLectureWithGuava(Lecture lecture, Venue venue,
int dayOfTheWeek, int hour) {
Preconditions.checkArgument(dayOfTheWeek > 0 && dayOfTheWeek <= 7,
"There are only 7 days of the week");
Preconditions.checkArgument(hour >= 0 && hour < 23,
"Day has only 24hours");
Preconditions.checkArgument(lecture != null, "Lecture cannot be null");
Lecture localLecture = Preconditions.checkNotNull(lecture);
Venue localVenue = Preconditions.checkNotNull(venue);
// reminder omitted
}
defensive programming
String[] csv;
for (String line : csv) {
String[] elements = line.split(",");
// reminder omitted
}
for (String line : csv) {
String[] r = StringUtils.split(line, ",");
r = StringUtils.stripAll(r);
}
for (String line : csv) {
Splitter.on(",")
.trimResults()
.omitEmptyStrings()
.split(line);
}
a później zawsze trafimy na String'a
public interface LectureService {
public Student[] getStudentsByYear(int year);
public Student[] getStudentsOlderThan(int age);
public Student[] getStudentsByBirthDate(Date date);
}
i kilka operacji 'biznesowych'
public Student[] getStudentsByYear(int year) {
final List<Student> students = new ArrayList<Student>();
for (Student s : lecture.getStudents()) {
if (s.getYear() == year) {
students.add(s);
}
}
return students.toArray(new Student[] {});
}
które sprowadzają się...
public Student[] getStudentsByBirthDate(Date date) {
final List<Student> students = new ArrayList<Student>();
for (Student s : lecture.getStudents()) {
Calendar studentBirth = Calendar.getInstance();
studentBirth.setTimeInMillis(s.getBirthDate());
Calendar desiredDate = Calendar.getInstance();
desiredDate.setTime(date);
if (studentBirth.get(Calendar.YEAR) ==
desiredDate.get(Calendar.YEAR)
&& studentBirth.get(Calendar.MONTH) ==
desiredDate.get(Calendar.MONTH)
&& studentBirth.get(Calendar.DATE) ==
desiredDate.get(Calendar.DATE)) {
students.add(s);
}
}
return students.toArray(new Student[] {});
}
... do niemal ...
public Student[] getStudentsOlderThan(int age) {
final List<Student> students = new ArrayList<Student>();
for (Student s : lecture.getStudents()) {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(s.getBirthDate());
c.add(Calendar.YEAR, age);
Calendar now = Calendar.getInstance();
now.setTime(new Date());
if (c.before(now)) {
students.add(s);
}
}
return students.toArray(new Student[] {});
}
... tego samego.
public Student[] getStudentsOlderThan(int age) {
final List<Student> students = new ArrayList<Student>();
for (Student s : lecture.getStudents()) {
DateMidnight dt = new DateMidnight()
.withMillis(s.getBirthDate())
.plusYears(age);
if (dt.isBeforeNow()) {
students.add(s);
}
}
return students.toArray(new Student[] {});
}
i abstahując od użycia JodaTime
private Student[] getStudents(Predicate predicate) {
final List<Student> students = new ArrayList<Student>();
for (Student s : lecture.getStudents()) {
if (predicate.evaluate(s)) {
students.add(s);
}
}
return students.toArray(new Student[] {});
}
Don't Repeat Yourself
Predicate predicate = new Predicate() {
@Override
public boolean evaluate(Object arg0) {
if (arg0 instanceof Student) {
Student s = (Student) arg0;
DateMidnight dt = new DateMidnight()
.withMillis(s.getBirthDate())
.plusYears(age);
if (dt.isBeforeNow()) {
return true;
}
}
return false;
}
};
No a ten predykat?
Predicate<Student> predicate = new Predicate<Student>() {
@Override
public boolean apply(Student input) {
DateMidnight dt = new DateMidnight()
.withMillis(input.getBirthDate())
.plusYears(age);
if (dt.isBeforeNow()) {
return true;
}
return false;
}
};
No a ten predykat? (2)
private Student[] getStudents(Predicate predicate) {
final List<Student> students = new ArrayList<Student>();
for (Student s : lecture.getStudents()) {
if (predicate.evaluate(s)) {
students.add(s);
}
}
return students.toArray(new Student[] {});
}
i jeszcze na koniec, zamiast...
protected Student[] getStudents(Predicate<Student> predicate) {
Iterable<Student> students = Iterables
.filter(Arrays.asList(lecture.getStudents()), predicate);
return Iterables.toArray(students, Student.class);
}
... może być w ogóle ślicznie
Student[] students = service.promoteStudents(2);
Predicate<Student> predicate = new Predicate<Student>() {
public boolean apply(Student input) {
if (input.getYear() == year) {
return true;
}
return false;
}
};
Function<Student,Student> function = new Function<Student,Student>(){
public Student apply(Student input) {
input.setYear(year + 1);
return input;
}
};
Iterables.filter();
Iterables.transform();
Jak już jest prawie funkcyjnie...
Guava to nie tylko <generics>
© Kevin Bourrillion, Google, Inc.
private Map<Student, List<Lecture>> classes =
new HashMap<Student, List<Lecture>>();
// ...
for (Lecture lecture : lectures) {
for (Student student : lecture.getStudents()) {
if (service.classes.containsKey(student)) {
service.classes.get(student).add(lecture);
} else {
List<Lecture> l = new ArrayList<Lecture>();
l.add(lecture);
service.classes.put(student, l);
}
}
}
kiedyś było tak...
private Multimap<Student, Lecture> classes =
ArrayListMultimap.create();
// ...
for (Lecture lecture : lectures) {
for (Student student : lecture.getStudents()) {
service.classes.put(student, lecture);
}
}
Map<Student, Collection<Lecture>> map = classes.asMap();
Collection<Lecture> lectures = classes.values();
Set<Student> students = classes.keySet();
for (Map.Entry<Student, Lecture> entry : classes.entries()) {}
... a teraz witamy Multimap i Multiset
Map<Student, Collection<Lecture>> map = classes.asMap();
"JM" => {"Fizyka", "Chemia", "Matematyka"}, "TD" => {"Chemia", Biologia"}
Collection<Lecture> lectures = classes.values();
{"Fizyka", "Matematyka", "Chemia", "Biologia"}
Set<Student> students = classes.keySet();
{"JM", "TD"}
for (Map.Entry<Student, Lecture> entry : classes.entries()) {}
{"JM"=>"Fizyka", "JM"=>"Matematyka", "JM"=>"Chemia", "TD"=>"Biologia", ...}
Collection<Lecture> lectures = classes.get("JM");
{"Fizyka", "Chemia", "Matematyka"}
Multimap i Multiset (2)
ImmutableSet<Student> students =
ImmutableSet.copyOf(service.getStudentsByYear(2));
Set<Student> students =
Collections.unmodifiableSet(
new LinkedHashSet<Student>(
Arrays.asList(service.getStudentsByYear(2))));
Immutability
new Person("Ridge", "Forrster");
Person person = new Person.Builder()
.withName(“Ridge”)
.withSurname(“Forrester”)
.build();
Immutability with builders
http://www.marchwicki.pl/blog/2010/11/building-a-pojo-in-an-elegant-way/
Dziękuje
http://marchwicki.pl/blog
@kubamarchwicki
http://www.delicious.com/kuba.marchwicki/beautifulcode
http://www.assembla.com/code/km_jug/subversion/nodes

More Related Content

What's hot

Hey Kotlin, How it works?
Hey Kotlin, How it works?Hey Kotlin, How it works?
Hey Kotlin, How it works?Chang W. Doh
 
(chapter 6) A Concise and Practical Introduction to Programming Algorithms in...
(chapter 6) A Concise and Practical Introduction to Programming Algorithms in...(chapter 6) A Concise and Practical Introduction to Programming Algorithms in...
(chapter 6) A Concise and Practical Introduction to Programming Algorithms in...Frank Nielsen
 
Java_practical_handbook
Java_practical_handbookJava_practical_handbook
Java_practical_handbookManusha Dilan
 
Java весна 2013 лекция 2
Java весна 2013 лекция 2Java весна 2013 лекция 2
Java весна 2013 лекция 2Technopark
 
Racing To Win: Using Race Conditions to Build Correct and Concurrent Software
Racing To Win: Using Race Conditions to Build Correct and Concurrent SoftwareRacing To Win: Using Race Conditions to Build Correct and Concurrent Software
Racing To Win: Using Race Conditions to Build Correct and Concurrent SoftwareFastly
 
Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Platonov Sergey
 
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...Sanjeev_Knoldus
 
From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019Leonardo Borges
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical FileSoumya Behera
 
Introduction à dart
Introduction à dartIntroduction à dart
Introduction à dartyohanbeschi
 
Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Chang W. Doh
 
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...Sergey Platonov
 
The Macronomicon
The MacronomiconThe Macronomicon
The MacronomiconMike Fogus
 
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour HadoopOSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour HadoopPublicis Sapient Engineering
 

What's hot (20)

Scala taxonomy
Scala taxonomyScala taxonomy
Scala taxonomy
 
Hey Kotlin, How it works?
Hey Kotlin, How it works?Hey Kotlin, How it works?
Hey Kotlin, How it works?
 
(chapter 6) A Concise and Practical Introduction to Programming Algorithms in...
(chapter 6) A Concise and Practical Introduction to Programming Algorithms in...(chapter 6) A Concise and Practical Introduction to Programming Algorithms in...
(chapter 6) A Concise and Practical Introduction to Programming Algorithms in...
 
Java_practical_handbook
Java_practical_handbookJava_practical_handbook
Java_practical_handbook
 
TechTalk - Dotnet
TechTalk - DotnetTechTalk - Dotnet
TechTalk - Dotnet
 
分散式系統
分散式系統分散式系統
分散式系統
 
Java весна 2013 лекция 2
Java весна 2013 лекция 2Java весна 2013 лекция 2
Java весна 2013 лекция 2
 
Racing To Win: Using Race Conditions to Build Correct and Concurrent Software
Racing To Win: Using Race Conditions to Build Correct and Concurrent SoftwareRacing To Win: Using Race Conditions to Build Correct and Concurrent Software
Racing To Win: Using Race Conditions to Build Correct and Concurrent Software
 
Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”
 
Lecture1 classes3
Lecture1 classes3Lecture1 classes3
Lecture1 classes3
 
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
 
From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical File
 
Scala 2013 review
Scala 2013 reviewScala 2013 review
Scala 2013 review
 
Introduction à dart
Introduction à dartIntroduction à dart
Introduction à dart
 
Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요Kotlin, 어떻게 동작하나요
Kotlin, 어떻게 동작하나요
 
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
 
The Macronomicon
The MacronomiconThe Macronomicon
The Macronomicon
 
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour HadoopOSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
 
Network
NetworkNetwork
Network
 

Viewers also liked

Rando vélo juillet 2010
Rando vélo juillet 2010Rando vélo juillet 2010
Rando vélo juillet 2010achribu
 
Pec_JuliaGUY
Pec_JuliaGUYPec_JuliaGUY
Pec_JuliaGUYroolli
 
[PL] Metadane - dane o danych
[PL] Metadane - dane o danych[PL] Metadane - dane o danych
[PL] Metadane - dane o danychJakub Marchwicki
 
GeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testingGeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testingJakub Marchwicki
 

Viewers also liked (7)

Rando vélo juillet 2010
Rando vélo juillet 2010Rando vélo juillet 2010
Rando vélo juillet 2010
 
Inputs
InputsInputs
Inputs
 
About the site.org
About the site.orgAbout the site.org
About the site.org
 
Pec_JuliaGUY
Pec_JuliaGUYPec_JuliaGUY
Pec_JuliaGUY
 
[PL] Metadane - dane o danych
[PL] Metadane - dane o danych[PL] Metadane - dane o danych
[PL] Metadane - dane o danych
 
About the site.org
About the site.orgAbout the site.org
About the site.org
 
GeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testingGeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testing
 

Similar to [PL] O klasycznej, programistycznej elegancji

How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeDaniel Wellman
 
Better Software: introduction to good code
Better Software: introduction to good codeBetter Software: introduction to good code
Better Software: introduction to good codeGiordano Scalzo
 
Fee managment system
Fee managment systemFee managment system
Fee managment systemfairy9912
 
Modul Praktek Java OOP
Modul Praktek Java OOP Modul Praktek Java OOP
Modul Praktek Java OOP Zaenal Arifin
 
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo....NET Conf UY
 
The Future of JVM Languages
The Future of JVM Languages The Future of JVM Languages
The Future of JVM Languages VictorSzoltysek
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETtdc-globalcode
 
Introduction à Dart
Introduction à DartIntroduction à Dart
Introduction à DartSOAT
 
import school.; import school.courses.;public class Main { p.pdf
import school.; import school.courses.;public class Main { p.pdfimport school.; import school.courses.;public class Main { p.pdf
import school.; import school.courses.;public class Main { p.pdfannaiwatertreatment
 
Scala in practice
Scala in practiceScala in practice
Scala in practicepatforna
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokusHamletDRC
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
JavaScript - Agora nervoso
JavaScript - Agora nervosoJavaScript - Agora nervoso
JavaScript - Agora nervosoLuis Vendrame
 
Starting with Main.java, where I tested everythingimport College..pdf
Starting with Main.java, where I tested everythingimport College..pdfStarting with Main.java, where I tested everythingimport College..pdf
Starting with Main.java, where I tested everythingimport College..pdfaptind
 
Ast transformations
Ast transformationsAst transformations
Ast transformationsHamletDRC
 
Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017Sunghyouk Bae
 

Similar to [PL] O klasycznej, programistycznej elegancji (20)

How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy Code
 
Better Software: introduction to good code
Better Software: introduction to good codeBetter Software: introduction to good code
Better Software: introduction to good code
 
Fee managment system
Fee managment systemFee managment system
Fee managment system
 
Modul Praktek Java OOP
Modul Praktek Java OOP Modul Praktek Java OOP
Modul Praktek Java OOP
 
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
 
The Future of JVM Languages
The Future of JVM Languages The Future of JVM Languages
The Future of JVM Languages
 
Functional C++
Functional C++Functional C++
Functional C++
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NET
 
Introduction à Dart
Introduction à DartIntroduction à Dart
Introduction à Dart
 
import school.; import school.courses.;public class Main { p.pdf
import school.; import school.courses.;public class Main { p.pdfimport school.; import school.courses.;public class Main { p.pdf
import school.; import school.courses.;public class Main { p.pdf
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Static and const members
Static and const membersStatic and const members
Static and const members
 
JavaScript - Agora nervoso
JavaScript - Agora nervosoJavaScript - Agora nervoso
JavaScript - Agora nervoso
 
Anti patterns
Anti patternsAnti patterns
Anti patterns
 
Starting with Main.java, where I tested everythingimport College..pdf
Starting with Main.java, where I tested everythingimport College..pdfStarting with Main.java, where I tested everythingimport College..pdf
Starting with Main.java, where I tested everythingimport College..pdf
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017
 

More from Jakub Marchwicki

Test with Spock like the first officer
Test with Spock like the first officerTest with Spock like the first officer
Test with Spock like the first officerJakub Marchwicki
 
Design principles 4 hackers - tech3camp (28142014)
Design principles 4 hackers - tech3camp (28142014)Design principles 4 hackers - tech3camp (28142014)
Design principles 4 hackers - tech3camp (28142014)Jakub Marchwicki
 
[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariowaćJakub Marchwicki
 
GeeCON 2013 - EJB application guided by tests
GeeCON 2013 - EJB application guided by testsGeeCON 2013 - EJB application guided by tests
GeeCON 2013 - EJB application guided by testsJakub Marchwicki
 
[PL] Jak programować aby nie zwariować?
[PL] Jak programować aby nie zwariować?[PL] Jak programować aby nie zwariować?
[PL] Jak programować aby nie zwariować?Jakub Marchwicki
 

More from Jakub Marchwicki (6)

Test with Spock like the first officer
Test with Spock like the first officerTest with Spock like the first officer
Test with Spock like the first officer
 
Design principles 4 hackers - tech3camp (28142014)
Design principles 4 hackers - tech3camp (28142014)Design principles 4 hackers - tech3camp (28142014)
Design principles 4 hackers - tech3camp (28142014)
 
JEE.next()
JEE.next()JEE.next()
JEE.next()
 
[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować
 
GeeCON 2013 - EJB application guided by tests
GeeCON 2013 - EJB application guided by testsGeeCON 2013 - EJB application guided by tests
GeeCON 2013 - EJB application guided by tests
 
[PL] Jak programować aby nie zwariować?
[PL] Jak programować aby nie zwariować?[PL] Jak programować aby nie zwariować?
[PL] Jak programować aby nie zwariować?
 

Recently uploaded

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 

Recently uploaded (20)

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 

[PL] O klasycznej, programistycznej elegancji

  • 1. O klasycznej programistycznej elegancji http://my.opera.com/rato53/albums/
  • 2. Jakub Marchwicki Technical Consultant Java, Lua, PHP i tak od 9lat marchwicki.pl/blog @kubamarchwicki
  • 5. „Any fool can write code that a computer can understand. Good programmers write code that humans can understand“ Refactoring: Improving the Design of Existing Code, 1999
  • 8. Effective Java I sure wish I had this book ten years ago James Gosling
  • 9. Kent Beck „Many people don’t realize how readable code can be and how valuable that readability is. Kent has taught me so...“ Martin Fowler
  • 10. Implementation patterns Communication Simplicity Flexibility A wszystko dlatego że największym kosztem oprogramowania będzie i tak jego utrzymanie
  • 11. Kryteria dobrego kodu © http://www.agileadvisor.com/
  • 12. private static boolean isOlderExtremeVersion(String d1, String d2) { String[] dateOneA = dateOne.split("-"); String[] dateTwoA = dateTwo.split("-"); if ((Integer.valueOf(dateOneA[0]).intValue() > Integer.valueOf(dateTwoA[0]).intValue()) || (Integer.valueOf(dateOneA[0]).intValue() == Integer.valueOf(dateTwoA[0]).intValue() && Integer.valueOf(dateOneA[1]).intValue() > Integer.valueOf(dateTwoA[1]).intValue()) || (Integer.valueOf(dateOneA[0]).intValue() == Integer.valueOf(dateTwoA[0]).intValue() && Integer.valueOf(dateOneA[1]).intValue() == Integer.valueOf(dateTwoA[1]).intValue() && Integer.valueOf(dateOneA[2]).intValue() > Integer.valueOf(dateTwoA[2]).intValue())) { return false; } return true; } Nie będzie Eclipsa...
  • 13. public class Person { private String firstName; private String lastName; private long birthDate; } public class Student extends Person { private int year; } public class Professor extends Person { private String[] specjalities; } public class Lecture { private String title; private Professor professor; private Student[] students; } Wyobraźmy sobie model...
  • 14. public boolean equals(Object o) { if (!(o instanceof Person)) return false; final Person p = (Person) o; return firstName.equals(p.firstName) && lastName.equals(p.lastName) && birthDate == p.birthDate; } public int hashcode() { int result = 17; result = 37*result + firstName.hashCode(); result = 37*result + lastName.hashCode(); result = 37*result + (int)(birthDate ^ birthDate >>> 32); return result; } A teraz piszemy...
  • 15. public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(specjalities); return result; } public boolean equals(Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (!(obj instanceof Professor)) { return false; } Professor other = (Professor) obj; if (!Arrays.equals(specjalities, other.specjalities)) { return false; } return true; } lub generujemy...
  • 16. public String toString() { return "Professor [specjalities=" + Arrays.toString(specjalities) + "]"; } to samo tyczy się toString()'a
  • 17. public boolean equals(Object o) { if (o == null) { return false; } if (o == this) { return true; } if (o.getClass() != getClass()) { return false; } final Student s = (Student) o; return new EqualsBuilder() .appendSuper(super.equals(o)).append(year, s.year) .isEquals(); } public int hashcode() { return new HashCodeBuilder(17, 37) .appendSuper(super.hashcode()).append(year) .toHashCode(); } public String toString() { return new ToStringBuilder(this) .appendSuper(super.toString()).append("year", year) .toString(); } ale przy setce encji się nie chcieć
  • 18. public boolean equals(Object o) { if (o instanceof Lecture) { Lecture l = (Lecture) o; return Objects.equal(professor, l.professor) && Objects.equal(students, l.students) && Objects.equal(title, l.title); } return false; } public int hashcode() { return Objects.hashCode(title, professor, students); } public String toString() { return Objects.toStringHelper(this) .add("professor", professor) .add("students", students) .toString(); } albo mniej fundamentalnie
  • 19. public void addLectureWithCommons(Lecture lecture, Venue venue, int dayOfTheWeek, int hour) { Validate.isTrue(dayOfTheWeek > 0 && dayOfTheWeek <= 7, "There are only 7 days of the week"); Validate.isTrue(hour >= 0 && hour < 23, "Day has only 24hours"); Validate.notNull(lecture != null, "Lecture cannot be null"); Validate.notNull(venue != null, "Venue cannot be null"); // reminder omitted } public void addLectureWithGuava(Lecture lecture, Venue venue, int dayOfTheWeek, int hour) { Preconditions.checkArgument(dayOfTheWeek > 0 && dayOfTheWeek <= 7, "There are only 7 days of the week"); Preconditions.checkArgument(hour >= 0 && hour < 23, "Day has only 24hours"); Preconditions.checkArgument(lecture != null, "Lecture cannot be null"); Lecture localLecture = Preconditions.checkNotNull(lecture); Venue localVenue = Preconditions.checkNotNull(venue); // reminder omitted } defensive programming
  • 20. String[] csv; for (String line : csv) { String[] elements = line.split(","); // reminder omitted } for (String line : csv) { String[] r = StringUtils.split(line, ","); r = StringUtils.stripAll(r); } for (String line : csv) { Splitter.on(",") .trimResults() .omitEmptyStrings() .split(line); } a później zawsze trafimy na String'a
  • 21. public interface LectureService { public Student[] getStudentsByYear(int year); public Student[] getStudentsOlderThan(int age); public Student[] getStudentsByBirthDate(Date date); } i kilka operacji 'biznesowych'
  • 22. public Student[] getStudentsByYear(int year) { final List<Student> students = new ArrayList<Student>(); for (Student s : lecture.getStudents()) { if (s.getYear() == year) { students.add(s); } } return students.toArray(new Student[] {}); } które sprowadzają się...
  • 23. public Student[] getStudentsByBirthDate(Date date) { final List<Student> students = new ArrayList<Student>(); for (Student s : lecture.getStudents()) { Calendar studentBirth = Calendar.getInstance(); studentBirth.setTimeInMillis(s.getBirthDate()); Calendar desiredDate = Calendar.getInstance(); desiredDate.setTime(date); if (studentBirth.get(Calendar.YEAR) == desiredDate.get(Calendar.YEAR) && studentBirth.get(Calendar.MONTH) == desiredDate.get(Calendar.MONTH) && studentBirth.get(Calendar.DATE) == desiredDate.get(Calendar.DATE)) { students.add(s); } } return students.toArray(new Student[] {}); } ... do niemal ...
  • 24. public Student[] getStudentsOlderThan(int age) { final List<Student> students = new ArrayList<Student>(); for (Student s : lecture.getStudents()) { Calendar c = Calendar.getInstance(); c.setTimeInMillis(s.getBirthDate()); c.add(Calendar.YEAR, age); Calendar now = Calendar.getInstance(); now.setTime(new Date()); if (c.before(now)) { students.add(s); } } return students.toArray(new Student[] {}); } ... tego samego.
  • 25. public Student[] getStudentsOlderThan(int age) { final List<Student> students = new ArrayList<Student>(); for (Student s : lecture.getStudents()) { DateMidnight dt = new DateMidnight() .withMillis(s.getBirthDate()) .plusYears(age); if (dt.isBeforeNow()) { students.add(s); } } return students.toArray(new Student[] {}); } i abstahując od użycia JodaTime
  • 26. private Student[] getStudents(Predicate predicate) { final List<Student> students = new ArrayList<Student>(); for (Student s : lecture.getStudents()) { if (predicate.evaluate(s)) { students.add(s); } } return students.toArray(new Student[] {}); } Don't Repeat Yourself
  • 27. Predicate predicate = new Predicate() { @Override public boolean evaluate(Object arg0) { if (arg0 instanceof Student) { Student s = (Student) arg0; DateMidnight dt = new DateMidnight() .withMillis(s.getBirthDate()) .plusYears(age); if (dt.isBeforeNow()) { return true; } } return false; } }; No a ten predykat?
  • 28. Predicate<Student> predicate = new Predicate<Student>() { @Override public boolean apply(Student input) { DateMidnight dt = new DateMidnight() .withMillis(input.getBirthDate()) .plusYears(age); if (dt.isBeforeNow()) { return true; } return false; } }; No a ten predykat? (2)
  • 29. private Student[] getStudents(Predicate predicate) { final List<Student> students = new ArrayList<Student>(); for (Student s : lecture.getStudents()) { if (predicate.evaluate(s)) { students.add(s); } } return students.toArray(new Student[] {}); } i jeszcze na koniec, zamiast...
  • 30. protected Student[] getStudents(Predicate<Student> predicate) { Iterable<Student> students = Iterables .filter(Arrays.asList(lecture.getStudents()), predicate); return Iterables.toArray(students, Student.class); } ... może być w ogóle ślicznie
  • 31. Student[] students = service.promoteStudents(2); Predicate<Student> predicate = new Predicate<Student>() { public boolean apply(Student input) { if (input.getYear() == year) { return true; } return false; } }; Function<Student,Student> function = new Function<Student,Student>(){ public Student apply(Student input) { input.setYear(year + 1); return input; } }; Iterables.filter(); Iterables.transform(); Jak już jest prawie funkcyjnie...
  • 32. Guava to nie tylko <generics> © Kevin Bourrillion, Google, Inc.
  • 33. private Map<Student, List<Lecture>> classes = new HashMap<Student, List<Lecture>>(); // ... for (Lecture lecture : lectures) { for (Student student : lecture.getStudents()) { if (service.classes.containsKey(student)) { service.classes.get(student).add(lecture); } else { List<Lecture> l = new ArrayList<Lecture>(); l.add(lecture); service.classes.put(student, l); } } } kiedyś było tak...
  • 34. private Multimap<Student, Lecture> classes = ArrayListMultimap.create(); // ... for (Lecture lecture : lectures) { for (Student student : lecture.getStudents()) { service.classes.put(student, lecture); } } Map<Student, Collection<Lecture>> map = classes.asMap(); Collection<Lecture> lectures = classes.values(); Set<Student> students = classes.keySet(); for (Map.Entry<Student, Lecture> entry : classes.entries()) {} ... a teraz witamy Multimap i Multiset
  • 35. Map<Student, Collection<Lecture>> map = classes.asMap(); "JM" => {"Fizyka", "Chemia", "Matematyka"}, "TD" => {"Chemia", Biologia"} Collection<Lecture> lectures = classes.values(); {"Fizyka", "Matematyka", "Chemia", "Biologia"} Set<Student> students = classes.keySet(); {"JM", "TD"} for (Map.Entry<Student, Lecture> entry : classes.entries()) {} {"JM"=>"Fizyka", "JM"=>"Matematyka", "JM"=>"Chemia", "TD"=>"Biologia", ...} Collection<Lecture> lectures = classes.get("JM"); {"Fizyka", "Chemia", "Matematyka"} Multimap i Multiset (2)
  • 36. ImmutableSet<Student> students = ImmutableSet.copyOf(service.getStudentsByYear(2)); Set<Student> students = Collections.unmodifiableSet( new LinkedHashSet<Student>( Arrays.asList(service.getStudentsByYear(2)))); Immutability
  • 37. new Person("Ridge", "Forrster"); Person person = new Person.Builder() .withName(“Ridge”) .withSurname(“Forrester”) .build(); Immutability with builders http://www.marchwicki.pl/blog/2010/11/building-a-pojo-in-an-elegant-way/