
Encapsulation
Explicit content warning
06/24/19 • 39 min
Episode 6 - More Code Examples
- Drawing from Chapter 7 - Encapsulation
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Encapsulate Record (162)
var organization = { name: "JP Sio", country: "USA" };becomes ⬇️
class Organization { constructor(data) { this._name = data.name; this._country = data.country; } get name() { return this._name; } set name(arg) { this._name = arg; } get country() { return this._country; } set country(arg) { this._country = arg; } }- you can hide what is stored and provide methods
- consumer of class Organization doesn't need to know / care which is stored and which is calculated
- nice getter and setter methods
- makes it easier to refactor -> can hide implementation of internals and update the internals while keeping the same external interface
Encapsulate Collection (170)
class Person { get courses() { return this._courses; } set courses(aList) { this._courses = aList; } }becomes ⬇️
class Person { get courses() { return this._courses.slice(); } addCourse(aCourse) { /*...*/ } }- slice() is key here, does not modify the original array - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
- common approach is to provide a getting method for the collection to return a copy
- basically, never mutate the original
Replace Primative with Object (174)
orders.filter(0 => "high" === o.priority || "rush" === o.priority)becomes ⬇️
orders.filter(o => o.priority.higherThan(new Priority("normal")));- this goes back to "Primitive Obsession"
- programmers are often hesitant to create their own types and rely only on primitives. i.e. representing a phone number as a string instead of as it's own type
A telephone number may be represented as a string for a while, but later it will need special behavior for formatting, extracting the area code, and the like
- create a new class for that bit of data
- at first, the class does very little. in fact it probably only wraps a primitive
- but now you have a place to put behavior specific to its needs
Inline Function (115) 🥴
Sometimes it's better to not try to split things apart, sometimes it just complicates things.
// before refactor: function getItemPrice(item) { if (itemOnSale(item) == true) { return item.price - 5 } else { return item.price } }; function itemOnSale(product) { if (product.onSale == true) { return true; } else { return false; } }; let original = getItemPrice(sweatshirt); // after refactor: function newGetItemPrice(item) { if (item.onSale == true) { return item.price - 5 } else { return item.price } };Extract Class (182) 🥴
- Talk through HUGE applicant model (in Ruby)
- Broke this into child objects
- Applicant Health History
- Applicant Habits
- Applicant Lifestyle
- Applicant Method
- Applicant Legal Release
Picks
- JP: None :(
- John: Quad Lock phone mount - bikes
Episode 6 - More Code Examples
- Drawing from Chapter 7 - Encapsulation
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Encapsulate Record (162)
var organization = { name: "JP Sio", country: "USA" };becomes ⬇️
class Organization { constructor(data) { this._name = data.name; this._country = data.country; } get name() { return this._name; } set name(arg) { this._name = arg; } get country() { return this._country; } set country(arg) { this._country = arg; } }- you can hide what is stored and provide methods
- consumer of class Organization doesn't need to know / care which is stored and which is calculated
- nice getter and setter methods
- makes it easier to refactor -> can hide implementation of internals and update the internals while keeping the same external interface
Encapsulate Collection (170)
class Person { get courses() { return this._courses; } set courses(aList) { this._courses = aList; } }becomes ⬇️
class Person { get courses() { return this._courses.slice(); } addCourse(aCourse) { /*...*/ } }- slice() is key here, does not modify the original array - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
- common approach is to provide a getting method for the collection to return a copy
- basically, never mutate the original
Replace Primative with Object (174)
orders.filter(0 => "high" === o.priority || "rush" === o.priority)becomes ⬇️
orders.filter(o => o.priority.higherThan(new Priority("normal")));- this goes back to "Primitive Obsession"
- programmers are often hesitant to create their own types and rely only on primitives. i.e. representing a phone number as a string instead of as it's own type
A telephone number may be represented as a string for a while, but later it will need special behavior for formatting, extracting the area code, and the like
- create a new class for that bit of data
- at first, the class does very little. in fact it probably only wraps a primitive
- but now you have a place to put behavior specific to its needs
Inline Function (115) 🥴
Sometimes it's better to not try to split things apart, sometimes it just complicates things.
// before refactor: function getItemPrice(item) { if (itemOnSale(item) == true) { return item.price - 5 } else { return item.price } }; function itemOnSale(product) { if (product.onSale == true) { return true; } else { return false; } }; let original = getItemPrice(sweatshirt); // after refactor: function newGetItemPrice(item) { if (item.onSale == true) { return item.price - 5 } else { return item.price } };Extract Class (182) 🥴
- Talk through HUGE applicant model (in Ruby)
- Broke this into child objects
- Applicant Health History
- Applicant Habits
- Applicant Lifestyle
- Applicant Method
- Applicant Legal Release
Picks
- JP: None :(
- John: Quad Lock phone mount - bikes
Previous Episode

Bad Smells in Code
Chapter 3 - Bad Smells in Code
The theme of this chapter: just because you know how to refactor, doesn't mean you know when. This chapter talks about the when.
One thing we won't try to give you is precise criteria for when a refactoring is overdue. In our experience, no set of metrics rivals informed human intuition. What we will do is give you indications that there is trouble that can be solved by a refactoring.
Mysterious Name
- there can be ambiguity in your naming in many places: variable, class, function, method, database field, etc
Duplicated Code 🔥
- keep it dry
Long Functions 🔥
- Since the early days of programming, people have realized that the longer a function is, the more difficult it is to understand
Long Parameter List 🔥
- long parameter lists can be confusing
Global Data 🔥
- the problem with global data is that it can be modified from anywhere in the codebase, making it harder to figure out which code touched it should you need to debug it
Mutable Data
- changes to data often lead to unexpected consequences and tricky bugs
- mutable data that can be calculated elsewhere is particularly pungent
Divergent Change ✅
- if you look at a module and say, "well, I will have to change these three functions every time -------- happens" - this is an indication of divergent change
- divergent change occurs when one module is often changed in different ways for different reasons
- can be solved with split phase, extract function, extract class, move function
Shotgun Surgery ✅
- similar to divergent change.
- every you make a change, you need to make a ton of little edits to a lot of different classes
Feature Envy
- occurs when a function in one module spends more time communicating with functions or data inside another module than it does within its own.
Data Clumps
- grouping data together when it really should be it's own object
Primitive Obsession ✅
- programmers are often hesitant to create their own types and rely only on primitives. i.e. representing a phone number as a string instead of as it's own type
Repeated Switches
- alleviated with polymorphism
Loops
- use pipelines instead, i.e. filter, map, each, reduce
Speculative Generality ✅
editor choice
- can be spotted when the only users of a function or class are a test case. this is a classic case of premature optimization. "we'll eventually want to add this feature..."
Message Chains
- when a client asks one object for another object, which the client then asks for yet another object, and so on.
Middle Man
- when you have too much delegation (due to all of your great encapsulating of implementation details)
- the solution is to delegate directly, cut the middle man
Insider Trading Large Class ✅
- class is doing too much
Alternative Classes with Different Interfaces Data Class Refused Bequest
Picks:
- JP: https://classicleatherfobs.co.uk/product-category/porsche/
- John: https://c-command.com/toothfairy/
Next Episode

Building Tests
Chapter 4 - Building Tests
To do refactoring properly, I need a solid suite of tests to spot my inevitable mistakes.
The Value of Self-Testing Code
- make sure all tests are fully automatic and that they check their own results
- a suite of tests is a powerful bug detector that decapitates the time it takes to find bugs
If you want to refactor, you have to write tests
A First Test
- simplicity of feedback from tests. just dots
- personally like verbose test output
Add Another Test
Testing should be risk driven; remember, I'm trying to find bugs, now or in the future. Therefore I don't test accessor methods that just read and write a field. They are so simple that I'm not likely to find a bug there.
My focus is to test areas that I'm most worried about going wrong.
Probing the Boundaries
- Seeing what happens when things go wrong
Whenever I have a collection of something, ... I like to see what happens when it's empty
- What happens when negative numbers are passed to a function that expects positive numbers? Division by zero?
How do you probe boundaries?
Much More Than This
When you get a bug report, start by writing a unit test that exposes the bug
Picks
- JP: Taking time off
If you like this episode you’ll love
Episode Comments
Generate a badge
Get a badge for your website that links back to this episode
<a href="https://goodpods.com/podcasts/iteration-225636/encapsulation-25584499"> <img src="https://storage.googleapis.com/goodpods-images-bucket/badges/generic-badge-1.svg" alt="listen to encapsulation on goodpods" style="width: 225px" /> </a>
Copy