SlideShare a Scribd company logo
Refactoring to
Immutability
@KevlinHenney
Refactoring to Immutability
Functional programming
Functional programming
typically avoids using
mutable state.
https://wiki.haskell.org/Functional_programming
https://xkcd.com/1270/
Functional programming
combines the flexibility
and power of abstract
mathematics with the
intuitive clarity of
abstract mathematics.
Rien n'est plus
dangereux qu'une
idée, quand on n'a
qu'une idée.
Émile-Auguste Chartier
Nothing is more
dangerous than an
idea, when you
have only one idea.
Émile-Auguste Chartier
String
Refactoring to Immutability
Asking a question
should not change
the answer.
To keep our C++ API boundary simple, we [...] adopted
one-way data flow. The API consists of methods to
perform fire-and-forget mutations and methods to
compute view models required by specific views.
To keep the code understandable, we write functional
style code converting raw data objects into immutable
view models by default. As we identified performance
bottlenecks through profiling, we added caches to avoid
recomputing unchanged intermediate results.
The resulting functional code is easy to maintain,
without sacrificing performance.
https://code.facebook.com/posts/498597036962415/under-the-hood-building-moments/
Refactoring to Immutability
Refactoring to Immutability
Refactoring to Immutability
Excel is the world's
most popular
functional language
Simon Peyton-Jones
I want code to
be reasonable
As a programmer
I want code to
be reasonable
reasonable
raisonnable
raison
raisonner
As a programmer
I want code to
be reasonable
so that I can
reason about it
A large fraction of the flaws in software development
are due to programmers not fully understanding all
the possible states their code may execute in.
In a multithreaded environment, the lack of
understanding and the resulting problems are
greatly amplified, almost to the point of panic if you
are paying attention.
John Carmack
http://www.gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php
Mutable
Immutable
Unshared Shared
Unshared mutable
data needs no
synchronisation
Unshared immutable
data needs no
synchronisation
Shared mutable
data needs
synchronisation
Shared immutable
data needs no
synchronisation
Mutable
Immutable
Unshared Shared
Unshared mutable
data needs no
synchronisation
Unshared immutable
data needs no
synchronisation
Shared mutable
data needs
synchronisation
Shared immutable
data needs no
synchronisation
The Synchronisation Quadrant
Refactoring to Immutability
Architecture represents the
significant design decisions
that shape a system, where
significant is measured by
cost of change.
Grady Booch
Refactoring to Immutability
µονόλιθος
There is a beautiful angel in that block
of marble, and I am going to find it.
All I have to do is to knock off the
outside pieces of marble, and be very
careful not to cut into the angel with
my chisel.
George F Pentecost
"The Angel in the Marble"
Refactoring to Immutability
Refactoring to Immutability
Functional
Operational
Developmental
Functional
Operational
Developmental
Refactoring to Immutability
Nothing is more
dangerous than an
idea, when you
have only one idea.
Émile-Auguste Chartier
Nothing is more
dangerous than
OO, when you have
only one object.
Refactoring to Immutability
public class Clock
{
public static Clock Instance => ...
public TimeOfDay Now => ...
...
}
public void Example()
{
var now = Clock.Instance.Now;
...
}
public void Example(Clock clock)
{
var now = clock.Now;
...
}
public interface Clock
{
TimeOfDay Now => ...
}
public class ClockImpl : Clock
{
public static Clock Instance => ...
...
}
public interface IClock
{
TimeOfDay Now => ...
}
public class Clock : IClock
{
public static IClock Instance => ...
...
}
public interface IClock
{
TimeOfDay Now => ...
}
public class LocalClock : IClock
{
public static IClock Instance => ...
...
}
public interface Clock
{
TimeOfDay Now => ...
}
public class LocalClock : Clock
{
public static Clock Instance => ...
...
}
public void Example(Func<TimeOfDay> timeOfDay)
{
var now = timeOfDay();
...
}
public void Example(TimeOfDay now)
{
...
}
public class TimeOfDay
{
...
public int Hour
{
get ...
set ...
}
public int Minute
{
get ...
set ...
}
public void NextHour() ...
public void NextMinute() ...
}
public class TimeOfDay
{
private int minutes;
public const int minutesInHour = 60;
public const int hoursInDay = 24;
public const int minutesInDay = hoursInDay * minutesInHour;
private static int Wrap(int minutes)
{
return minutes % minutesInDay;
}
public int Hour
{
get
{
return minutes / minutesInHour;
}
set
{
if (value < 0 || value >= hoursInDay)
throw new ArgumentException();
minutes = Wrap(value * minutesInHour + Minute);
}
}
public int Minute
{
get
{
return minutes % minutesInHour;
}
set
{
if (value < 0 || value >= minutesInHour)
throw new ArgumentException();
minutes = Wrap(Hour * minutesInHour + value);
}
}
public void NextHour()
{
minutes = Wrap(minutes + minutesInHour);
}
public void NextMinute()
{
minutes = Wrap(minutes + 1);
}
}
public class TimeOfDay
{
...
public int Hour
{
get ...
set ...
}
public int Minute
{
get ...
set ...
}
public void NextHour() ...
public void NextMinute() ...
}
public class TimeOfDay
{
...
public int Hour
{
get ...
set ...
}
public int Minute
{
get ...
set ...
}
}
public class TimeOfDay
{
...
public int Hour
{
get ...
}
public int Minute
{
get ...
}
}
public class TimeOfDay
{
...
public int Hour => ...
public int Minute => ...
}
public class TimeOfDay
{
...
public TimeOfDay(int hour, int minute) ...
public int Hour => ...
public int Minute => ...
}
public class TimeOfDay
{
...
public TimeOfDay(int hour, int minute) ...
public int Hour => ...
public int Minute => ...
public TimeOfDay WithHour(int newHour) ...
public TimeOfDay WithMinute(int newMinute) ...
}
public class TimeOfDay
{
...
public TimeOfDay(int hour, int minute) ...
public int Hour => ...
public int Minute => ...
public TimeOfDay WithHour(int newHour) ...
public TimeOfDay WithMinute(int newMinute) ...
public TimeOfDay NextHour() ...
public TimeOfDay NextMinute() ...
}
public class TimeOfDay
{
...
public TimeOfDay(int hour, int minute) ...
public int Hour => ...
public int Minute => ...
public TimeOfDay WithHour(int newHour) ...
public TimeOfDay WithMinute(int newMinute) ...
public TimeOfDay NextHour() ...
public TimeOfDay NextMinute() ...
public class Builder
{
...
}
}
public class TimeOfDay
{
private readonly int minutes;
public const int minutesInHour = 60;
public const int hoursInDay = 24;
public const int minutesInDay = hoursInDay * minutesInHour;
private TimeOfDay(int minutes)
{
this.minutes = minutes % minutesInDay;
}
public TimeOfDay(int hour, int minute)
{
if (hour < 0 || hour >= hoursInDay || minute < 0 || minute >= minutesInHour)
throw new ArgumentException();
minutes = hour * minutesInHour + minute;
}
public int Hour => minutes / minutesInHour;
public int Minute => minutes % minutesInHour;
public TimeOfDay WithHour(int newHour) => new TimeOfDay(newHour, Minute);
public TimeOfDay WithMinute(int newMinute) => new TimeOfDay(Hour, newMinute);
public TimeOfDay NextHour() => new TimeOfDay(minutes + minutesInHour);
public TimeOfDay NextMinute() => new TimeOfDay(minutes + 1);
...
}
Refactoring to Immutability
try {
Integer.parseInt(time.substring(0, 2));
}
catch (Exception x) {
return false;
}
if (Integer.parseInt(time.substring(0, 2)) > 12) {
return false;
}
...
if (!time.substring(9, 11).equals("AM") &
!time.substring(9, 11).equals("PM")) {
return false;
}
Burk Hufnagel
"Put the Mouse Down and Step Away from the Keyboard"
Burk Hufnagel
"Put the Mouse Down and Step Away from the Keyboard"
return time.matches("(0[1-9]|1[0-2]):[0-5][0-9]:[0-5][0-9] ([AP]M)");
Je n'ai fait celle-ci plus
longue que parce que je
n'ai pas eu le loisir de la
faire plus courte.
Blaise Pascal
I have made this [letter]
longer than usual
because I have not had
time to make it shorter.
Blaise Pascal
Refactoring to Immutability
Refactoring to Immutability
// Get the unique surnames in uppercase of the
// first 15 book authors that are 50 years old
// or older?
library.stream()
.map(book -> book.getAuthor())
.filter(author -> author.getAge() >= 50)
.limit(15)
.map(Author::getSurname)
.map(String::toUpperCase)
.distinct()
.collect(toList())
// Get the first 15 unique surnames in
// uppercase of the book authors that are 50
// years old or older.
library.stream()
.map(book -> book.getAuthor())
.filter(author -> author.getAge() >= 50)
.map(Author::getSurname)
.map(String::toUpperCase)
.distinct()
.limit(15)
.collect(toList())
// Get the unique surnames in uppercase of the
// first 15 book authors that are 50 years old
// or older.
library.stream()
.map(book -> book.getAuthor())
.filter(author -> author.getAge() >= 50)
.distinct()
.limit(15)
.map(Author::getSurname)
.map(String::toUpperCase)
.distinct()
.collect(toList())
// Get the unique surnames in uppercase of the
// first 15 book authors that are 50 years old
// or older.
library.stream()
.map(book -> book.getAuthor())
.distinct()
.filter(author -> author.getAge() >= 50)
.limit(15)
.map(Author::getSurname)
.map(String::toUpperCase)
.distinct()
.collect(toList())
Refactoring to Immutability
// Get the unique surnames in uppercase of the
// first 15 book authors that are 50 years old
// or older?
List<Author> authors = new ArrayList<Author>();
for (Book book : library)
{
Author author = book.getAuthor();
if (author.getAge() >= 50)
{
authors.add(author);
if (authors.size() == 15)
break;
}
// Get the unique surnames in uppercase of the
// first 15 book authors that are 50 years old
// or older?
List<Author> authors = new ArrayList<Author>();
for (Book book : library)
{
Author author = book.getAuthor();
if (author.getAge() >= 50)
{
authors.add(author);
if (authors.size() == 15)
break;
}
}
List<String> result = new ArrayList<String>();
for(Author author : authors)
{
String name = author.getSurname().toUpperCase();
if (!result.contains(name))
result.add(name);
}
// Get the first 15 unique surnames in
// uppercase of the book authors that are 50
// years old or older.
List<String> result = new ArrayList<String>();
for (Book book : library)
{
Author author = book.getAuthor();
if (author.getAge() >= 50)
{
String name = author.getSurname().toUpperCase();
if (!result.contains(name))
{
result.add(name);
if (result.size() == 15)
break;
}
}
}
// Get the unique surnames in uppercase of the
// first 15 book authors that are 50 years old
// or older.
List<Author> authors = new ArrayList<Author>();
for (Book book : library)
{
Author author = book.getAuthor();
if (author.getAge() >= 50 && !authors.contains(author))
{
authors.add(author);
if (authors.size() == 15)
break;
}
}
List<String> result = new ArrayList<String>();
for(Author author : authors)
{
String name = author.getSurname().toUpperCase();
if (!result.contains(name))
result.add(name);
}
Try to leave out the part
that readers tend to skip.
Elmore Leonard
When it is not necessary
to change, it is necessary
not to change.
Lucius Cary

More Related Content

PDF
Китайський дракон – міф чи реальна історія? : образ Дракона в китайській мі...
PDF
Addiction And Attachment Theory
PPT
ми – за здоровий спосіб життя
PDF
Functional C++
PDF
Refactor legacy code through pure functions
PDF
Look Mommy, No GC! (TechDays NL 2017)
PPTX
Good functional programming is good programming
PDF
Functional programming techniques in regular JavaScript
Китайський дракон – міф чи реальна історія? : образ Дракона в китайській мі...
Addiction And Attachment Theory
ми – за здоровий спосіб життя
Functional C++
Refactor legacy code through pure functions
Look Mommy, No GC! (TechDays NL 2017)
Good functional programming is good programming
Functional programming techniques in regular JavaScript

Similar to Refactoring to Immutability (20)

PPTX
.Net Collection Classes Deep Dive - Rocksolid Tour 2013
PPT
Class ‘increment’
PPTX
Vendredi Tech_ la programmation fonctionnelle.pptx
PPTX
Cleaner Code - CodeStock 2019 Edition
KEY
Clean code and Code Smells
PDF
Sony C#/.NET component set analysis
PDF
7 Habits For a More Functional Swift
PDF
If You Think You Can Stay Away from Functional Programming, You Are Wrong
PDF
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
PPTX
FP Day 2011 - Turning to the Functional Side (using C# & F#)
PPTX
Functional Programming with C#
PPTX
Code Metrics
PPTX
Pragmatic Performance from NDC London 2019
PPTX
Pragmatic Performance from NDC Oslo 2019
PPTX
Laziness, trampolines, monoids and other functional amenities: this is not yo...
PPTX
Writing Good Tests
PDF
Number 1 I have completed and number 6 is just uploading I .pdf
PDF
Experiments in Reasoning
PDF
Software Development - Thinking Object's Way
PPTX
What's new in C# 6.0
.Net Collection Classes Deep Dive - Rocksolid Tour 2013
Class ‘increment’
Vendredi Tech_ la programmation fonctionnelle.pptx
Cleaner Code - CodeStock 2019 Edition
Clean code and Code Smells
Sony C#/.NET component set analysis
7 Habits For a More Functional Swift
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
FP Day 2011 - Turning to the Functional Side (using C# & F#)
Functional Programming with C#
Code Metrics
Pragmatic Performance from NDC London 2019
Pragmatic Performance from NDC Oslo 2019
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Writing Good Tests
Number 1 I have completed and number 6 is just uploading I .pdf
Experiments in Reasoning
Software Development - Thinking Object's Way
What's new in C# 6.0
Ad

More from Kevlin Henney (20)

PDF
Program with GUTs
PDF
The Case for Technical Excellence
PDF
Empirical Development
PDF
Lambda? You Keep Using that Letter
PDF
Lambda? You Keep Using that Letter
PDF
Solid Deconstruction
PDF
Get Kata
PDF
Procedural Programming: It’s Back? It Never Went Away
PDF
Structure and Interpretation of Test Cases
PDF
Agility ≠ Speed
PDF
Old Is the New New
PDF
Turning Development Outside-In
PDF
Giving Code a Good Name
PDF
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
PDF
Thinking Outside the Synchronisation Quadrant
PDF
Code as Risk
PDF
Software Is Details
PDF
Game of Sprints
PDF
Good Code
PDF
The Error of Our Ways
Program with GUTs
The Case for Technical Excellence
Empirical Development
Lambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
Solid Deconstruction
Get Kata
Procedural Programming: It’s Back? It Never Went Away
Structure and Interpretation of Test Cases
Agility ≠ Speed
Old Is the New New
Turning Development Outside-In
Giving Code a Good Name
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Thinking Outside the Synchronisation Quadrant
Code as Risk
Software Is Details
Game of Sprints
Good Code
The Error of Our Ways
Ad

Recently uploaded (20)

PDF
Understanding Forklifts - TECH EHS Solution
PDF
medical staffing services at VALiNTRY
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
System and Network Administraation Chapter 3
PDF
System and Network Administration Chapter 2
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PPTX
history of c programming in notes for students .pptx
Understanding Forklifts - TECH EHS Solution
medical staffing services at VALiNTRY
How to Migrate SBCGlobal Email to Yahoo Easily
VVF-Customer-Presentation2025-Ver1.9.pptx
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
System and Network Administraation Chapter 3
System and Network Administration Chapter 2
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Softaken Excel to vCard Converter Software.pdf
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Navsoft: AI-Powered Business Solutions & Custom Software Development
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
CHAPTER 2 - PM Management and IT Context
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
history of c programming in notes for students .pptx

Refactoring to Immutability

  • 4. Functional programming typically avoids using mutable state. https://wiki.haskell.org/Functional_programming
  • 5. https://xkcd.com/1270/ Functional programming combines the flexibility and power of abstract mathematics with the intuitive clarity of abstract mathematics.
  • 6. Rien n'est plus dangereux qu'une idée, quand on n'a qu'une idée. Émile-Auguste Chartier
  • 7. Nothing is more dangerous than an idea, when you have only one idea. Émile-Auguste Chartier
  • 10. Asking a question should not change the answer.
  • 11. To keep our C++ API boundary simple, we [...] adopted one-way data flow. The API consists of methods to perform fire-and-forget mutations and methods to compute view models required by specific views. To keep the code understandable, we write functional style code converting raw data objects into immutable view models by default. As we identified performance bottlenecks through profiling, we added caches to avoid recomputing unchanged intermediate results. The resulting functional code is easy to maintain, without sacrificing performance. https://code.facebook.com/posts/498597036962415/under-the-hood-building-moments/
  • 15. Excel is the world's most popular functional language Simon Peyton-Jones
  • 16. I want code to be reasonable
  • 17. As a programmer I want code to be reasonable
  • 22. As a programmer I want code to be reasonable so that I can reason about it
  • 23. A large fraction of the flaws in software development are due to programmers not fully understanding all the possible states their code may execute in. In a multithreaded environment, the lack of understanding and the resulting problems are greatly amplified, almost to the point of panic if you are paying attention. John Carmack http://www.gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php
  • 24. Mutable Immutable Unshared Shared Unshared mutable data needs no synchronisation Unshared immutable data needs no synchronisation Shared mutable data needs synchronisation Shared immutable data needs no synchronisation
  • 25. Mutable Immutable Unshared Shared Unshared mutable data needs no synchronisation Unshared immutable data needs no synchronisation Shared mutable data needs synchronisation Shared immutable data needs no synchronisation The Synchronisation Quadrant
  • 27. Architecture represents the significant design decisions that shape a system, where significant is measured by cost of change. Grady Booch
  • 30. There is a beautiful angel in that block of marble, and I am going to find it. All I have to do is to knock off the outside pieces of marble, and be very careful not to cut into the angel with my chisel. George F Pentecost "The Angel in the Marble"
  • 36. Nothing is more dangerous than an idea, when you have only one idea. Émile-Auguste Chartier
  • 37. Nothing is more dangerous than OO, when you have only one object.
  • 39. public class Clock { public static Clock Instance => ... public TimeOfDay Now => ... ... }
  • 40. public void Example() { var now = Clock.Instance.Now; ... }
  • 41. public void Example(Clock clock) { var now = clock.Now; ... }
  • 42. public interface Clock { TimeOfDay Now => ... } public class ClockImpl : Clock { public static Clock Instance => ... ... }
  • 43. public interface IClock { TimeOfDay Now => ... } public class Clock : IClock { public static IClock Instance => ... ... }
  • 44. public interface IClock { TimeOfDay Now => ... } public class LocalClock : IClock { public static IClock Instance => ... ... }
  • 45. public interface Clock { TimeOfDay Now => ... } public class LocalClock : Clock { public static Clock Instance => ... ... }
  • 46. public void Example(Func<TimeOfDay> timeOfDay) { var now = timeOfDay(); ... }
  • 48. public class TimeOfDay { ... public int Hour { get ... set ... } public int Minute { get ... set ... } public void NextHour() ... public void NextMinute() ... }
  • 49. public class TimeOfDay { private int minutes; public const int minutesInHour = 60; public const int hoursInDay = 24; public const int minutesInDay = hoursInDay * minutesInHour; private static int Wrap(int minutes) { return minutes % minutesInDay; } public int Hour { get { return minutes / minutesInHour; } set { if (value < 0 || value >= hoursInDay) throw new ArgumentException(); minutes = Wrap(value * minutesInHour + Minute); } } public int Minute { get { return minutes % minutesInHour; } set { if (value < 0 || value >= minutesInHour) throw new ArgumentException(); minutes = Wrap(Hour * minutesInHour + value); } } public void NextHour() { minutes = Wrap(minutes + minutesInHour); } public void NextMinute() { minutes = Wrap(minutes + 1); } }
  • 50. public class TimeOfDay { ... public int Hour { get ... set ... } public int Minute { get ... set ... } public void NextHour() ... public void NextMinute() ... }
  • 51. public class TimeOfDay { ... public int Hour { get ... set ... } public int Minute { get ... set ... } }
  • 52. public class TimeOfDay { ... public int Hour { get ... } public int Minute { get ... } }
  • 53. public class TimeOfDay { ... public int Hour => ... public int Minute => ... }
  • 54. public class TimeOfDay { ... public TimeOfDay(int hour, int minute) ... public int Hour => ... public int Minute => ... }
  • 55. public class TimeOfDay { ... public TimeOfDay(int hour, int minute) ... public int Hour => ... public int Minute => ... public TimeOfDay WithHour(int newHour) ... public TimeOfDay WithMinute(int newMinute) ... }
  • 56. public class TimeOfDay { ... public TimeOfDay(int hour, int minute) ... public int Hour => ... public int Minute => ... public TimeOfDay WithHour(int newHour) ... public TimeOfDay WithMinute(int newMinute) ... public TimeOfDay NextHour() ... public TimeOfDay NextMinute() ... }
  • 57. public class TimeOfDay { ... public TimeOfDay(int hour, int minute) ... public int Hour => ... public int Minute => ... public TimeOfDay WithHour(int newHour) ... public TimeOfDay WithMinute(int newMinute) ... public TimeOfDay NextHour() ... public TimeOfDay NextMinute() ... public class Builder { ... } }
  • 58. public class TimeOfDay { private readonly int minutes; public const int minutesInHour = 60; public const int hoursInDay = 24; public const int minutesInDay = hoursInDay * minutesInHour; private TimeOfDay(int minutes) { this.minutes = minutes % minutesInDay; } public TimeOfDay(int hour, int minute) { if (hour < 0 || hour >= hoursInDay || minute < 0 || minute >= minutesInHour) throw new ArgumentException(); minutes = hour * minutesInHour + minute; } public int Hour => minutes / minutesInHour; public int Minute => minutes % minutesInHour; public TimeOfDay WithHour(int newHour) => new TimeOfDay(newHour, Minute); public TimeOfDay WithMinute(int newMinute) => new TimeOfDay(Hour, newMinute); public TimeOfDay NextHour() => new TimeOfDay(minutes + minutesInHour); public TimeOfDay NextMinute() => new TimeOfDay(minutes + 1); ... }
  • 60. try { Integer.parseInt(time.substring(0, 2)); } catch (Exception x) { return false; } if (Integer.parseInt(time.substring(0, 2)) > 12) { return false; } ... if (!time.substring(9, 11).equals("AM") & !time.substring(9, 11).equals("PM")) { return false; } Burk Hufnagel "Put the Mouse Down and Step Away from the Keyboard"
  • 61. Burk Hufnagel "Put the Mouse Down and Step Away from the Keyboard" return time.matches("(0[1-9]|1[0-2]):[0-5][0-9]:[0-5][0-9] ([AP]M)");
  • 62. Je n'ai fait celle-ci plus longue que parce que je n'ai pas eu le loisir de la faire plus courte. Blaise Pascal
  • 63. I have made this [letter] longer than usual because I have not had time to make it shorter. Blaise Pascal
  • 66. // Get the unique surnames in uppercase of the // first 15 book authors that are 50 years old // or older? library.stream() .map(book -> book.getAuthor()) .filter(author -> author.getAge() >= 50) .limit(15) .map(Author::getSurname) .map(String::toUpperCase) .distinct() .collect(toList())
  • 67. // Get the first 15 unique surnames in // uppercase of the book authors that are 50 // years old or older. library.stream() .map(book -> book.getAuthor()) .filter(author -> author.getAge() >= 50) .map(Author::getSurname) .map(String::toUpperCase) .distinct() .limit(15) .collect(toList())
  • 68. // Get the unique surnames in uppercase of the // first 15 book authors that are 50 years old // or older. library.stream() .map(book -> book.getAuthor()) .filter(author -> author.getAge() >= 50) .distinct() .limit(15) .map(Author::getSurname) .map(String::toUpperCase) .distinct() .collect(toList())
  • 69. // Get the unique surnames in uppercase of the // first 15 book authors that are 50 years old // or older. library.stream() .map(book -> book.getAuthor()) .distinct() .filter(author -> author.getAge() >= 50) .limit(15) .map(Author::getSurname) .map(String::toUpperCase) .distinct() .collect(toList())
  • 71. // Get the unique surnames in uppercase of the // first 15 book authors that are 50 years old // or older? List<Author> authors = new ArrayList<Author>(); for (Book book : library) { Author author = book.getAuthor(); if (author.getAge() >= 50) { authors.add(author); if (authors.size() == 15) break; }
  • 72. // Get the unique surnames in uppercase of the // first 15 book authors that are 50 years old // or older? List<Author> authors = new ArrayList<Author>(); for (Book book : library) { Author author = book.getAuthor(); if (author.getAge() >= 50) { authors.add(author); if (authors.size() == 15) break; } } List<String> result = new ArrayList<String>(); for(Author author : authors) { String name = author.getSurname().toUpperCase(); if (!result.contains(name)) result.add(name); }
  • 73. // Get the first 15 unique surnames in // uppercase of the book authors that are 50 // years old or older. List<String> result = new ArrayList<String>(); for (Book book : library) { Author author = book.getAuthor(); if (author.getAge() >= 50) { String name = author.getSurname().toUpperCase(); if (!result.contains(name)) { result.add(name); if (result.size() == 15) break; } } }
  • 74. // Get the unique surnames in uppercase of the // first 15 book authors that are 50 years old // or older. List<Author> authors = new ArrayList<Author>(); for (Book book : library) { Author author = book.getAuthor(); if (author.getAge() >= 50 && !authors.contains(author)) { authors.add(author); if (authors.size() == 15) break; } } List<String> result = new ArrayList<String>(); for(Author author : authors) { String name = author.getSurname().toUpperCase(); if (!result.contains(name)) result.add(name); }
  • 75. Try to leave out the part that readers tend to skip. Elmore Leonard
  • 76. When it is not necessary to change, it is necessary not to change. Lucius Cary