RubyConf 2023

The Unbreakable Code Whose Breaking Won WWII

The Unbreakable Code Whose Breaking Won WWII

by Aji Slater

The video titled "The Unbreakable Code Whose Breaking Won WWII" presented by Aji Slater at RubyConf 2023 delves into the intriguing history and mechanics of the Enigma machine, a pivotal tool for German military encryption during World War II. The speaker connects historical insights with modern object-oriented programming (OOP) principles, demonstrating how the design of the Enigma informs contemporary software development practices.

Key points covered in the video include:
- Introduction to the Enigma Machine: The Enigma was a complex encryption device used by the Germans to secure military communications. It operated using rotors that changed the electrical path of keyed letters, making each letter's encryption unique with every keystroke.
- Bletchley Park's Role: The British effort to break the Enigma code was centered at Bletchley Park, led by notable figures like Alan Turing. Their work is credited with shortening the war significantly.
- Mechanics of the Enigma: A detailed description of how the machine encoded and decoded messages through a series of electrical connections, leveraging a combination of rotors and plugboards to create a massive number of potential settings.
- Object-Oriented Programming (OOP) Principles: Aji outlines essential OOP concepts, such as the Single Responsibility Principle, Abstraction, Encapsulation, Dependency Inversion, and the Open-Closed Principle, drawing parallels between the physical components of the Enigma and software development practices.
- Building an Enigma Emulator in Ruby: The speaker engages the audience through a programming demonstration to create a simplified emulator of the Enigma machine using Ruby, employing test-driven development for coding classes that reflect the machine’s functionality.
- Affirmations of Good Practices: The presentation illustrates coding best practices, encouraging encapsulation and abstraction to ensure that components remain modular and adaptable to change.

The main takeaway from this session is the reflection on how the engineering principles applied in the design of the Enigma machine can direct modern programming strategies, emphasizing the importance of modular design and adaptability in software development. Aji inspires the audience to consider these historical lessons as they engage with contemporary codebases, demonstrating that the challenges of coding reflect the complexities faced during wartime code-breaking. Furthermore, Aji invites attendees to explore further applications, including more advanced functionalities for the Enigma emulator, showing the ongoing relevance of this historical technology in today’s programming landscape.

00:00:18 Good afternoon, everyone. My name is Nol Rappen from the RubyConf programming committee. I would like to introduce Aji Slater.
00:00:24 Aji started their career as a villain but in 2015 traded many bits for digital ones, performing with React and Rails instead of elephants.
00:00:30 I have so many comments here, but I'm not even going to go there. Aji is co-host of the Tightly Cobble Book Club podcast and according to this, is probably not Banksy.
00:00:37 Please give a lovely Ruby welcome to Aji Slater!
00:01:03 So if you’re able and so inclined, I’d like you to stand up for a moment. We’re just going to get a little stretch, get some blood flowing, and get some endorphins going.
00:01:17 Let’s reach up and dive into a pool with a little forward stretch and a little backward stretch. Cool! Thanks!
00:01:34 Alright, thanks everybody for coming out. There’s going to be code up here, so if that’s important to you to read, feel free to move on.
00:01:48 As I mentioned, my name is Aji and I work at a place called Thoughtbot.
00:01:56 You may have learned that in the 1930s and 40s, there was a war involving many nations across the globe. In fact, they called it a World War. It was the second of its kind.
00:02:14 The particulars of the conflict are not what we’re going to discuss today, but if you’re interested in the period, I believe there have been a few movies, TV shows, and even books where you can find out more.
00:02:28 For our purposes today, all that’s important is knowing that on opposing sides of the conflict were Germany and the United Kingdom.
00:02:31 At the time, long-distance communication was done in Morse code over radio, which can be intercepted by an opponent in much the same way that we intercept the local Top 40 station.
00:02:49 The messages would need to be encrypted, and the German solution for encryption was the Enigma machine.
00:03:06 Not that much bigger than a typewriter, the Enigma would encipher a given message before it was sent over the airwaves.
00:03:18 The receiver of the message would also have an Enigma, and given the same settings that encoded the transmission, they could reconstruct the original message.
00:03:31 The British solution for decrypting was Bletchley Park. This estate in Buckinghamshire was Britain’s GC&CS, the government code and cipher school.
00:03:43 The work of Bletchley was kept secret until the 1970s and several thousand men and women, mostly women and mostly college-aged, were tasked with cracking the German enciphering system.
00:03:57 If you know the story of Bletchley, you’ve likely heard of Alan Turing, the Turing test, Turing machines, or Turing patterns.
00:04:07 Maybe you know the negative proof of the Shid, or you’ve just seen him on the £50 note.
00:04:17 Building on the work of Polish codebreaker Marian Rejewski and his precursor machine called Bomba, Turing realized that a quirk of Enigma's wiring could be exploited.
00:04:41 He designed a special purpose computational engine that was made real by the engineering brilliance of Harold Keen and the British Tabulating Machine Company.
00:05:00 After incorporating a crucial insight by English mathematician Gordon Welshman, Bletchley’s secret weapon was christened Bombe, with 108 cascading rotating drums.
00:05:12 The Bombe could crunch through 17,576 possible Enigma settings in just 20 minutes.
00:05:25 Depending on who you ask, the work at Bletchley shortened the war by 2 to 4 years.
00:05:43 If you’re interested in hearing more about what it was like to be a part of the Bletchley operation, I would really recommend 'The Secret Lives of Codebreakers' by Sinclair McKay.
00:05:58 The Enigma was operated by German communication agents working in pairs. One agent would operate the keyboard, entering the message, while the corresponding letter would light up on a lamp board and be written down by the second.
00:06:16 It worked like this: it’s a simple electronic circuit, and if you’re unfamiliar with that sort of thing, you can think of the wire as a tube that carries electricity. When the switch is down, the signal flows, and when that signal touches a light, it will illuminate.
00:06:46 Now imagine that there are more of these simple circuits, 26 of them, from A to A, B to B, C to C, on down the alphabet.
00:06:59 If the connections between the key and light are changed, then the signal would be encoded. Press the A key, and B lights up. If you knew which letters were connected, you would be able to decode it as well.
00:07:27 That’s the job of Enigma’s encryption mechanism. It physically swaps the electrical connection between the key and the light.
00:07:45 Maybe you've made a code like this before when one letter is replaced by another — this is known as a substitution cipher. However, no matter how much the key is scrambled, substitution ciphers are trivial to break.
00:08:02 So at the heart of Enigma’s encryption engine are several rotors. Each rotor has 26 electrical contacts on each side and can be turned to set the machine at any one of those positions.
00:08:23 Internally, a wire goes from a contact on one side to a different contact on the other side.
00:08:34 The signal might come into index zero on the right side and be wired to index eight on the left, then two to twenty-one, three to fourteen, and so on.
00:08:52 However, if it remained as simple as a substitution cipher, it would be just as easy to decode.
00:09:10 Enigma accepted three rotors, each with different internal connections. But there were also five rotors to choose from, and those five could be entered in any order, resulting in 60 possible combinations.
00:09:39 When mounted on the internal spindle, the rotors’ 26 connection points lined up, and a signal would be sent through them coming in from the keyboard before being switched to different indexes by each rotor in turn.
00:09:54 After the three rotors came a special rotor called a reflector. Here, if 1 becomes 10, then 10 becomes 1. After passing through the reflector, the signal would be carried back along a different path of connections.
00:10:12 This is how Enigma both encrypted and decrypted messages; the path of the signal is symmetrical, meaning that typing the cipher character will return the original.
00:10:30 But no matter how many times a letter is changed, it’s weak. If 'A' always becomes 'E', then the rotors rotate after each character, allowing the signal to take a new path.
00:10:52 This means the same key pressed twice in a row would yield two different encoded letters.
00:11:14 Techniques that make a substitution cipher easy to break rely on repetition and statistical analysis, and they are useless against a key that changes not once a day or once per message, but once per keystroke.
00:11:31 The rotors didn’t all rotate at the same speed; the second wheel wouldn’t advance until the first one made a full revolution and so on.
00:11:44 This means Enigma was a polyalphabetic cipher, with a new key for every letter based on the starting settings of the machine. Each rotor had 26 positions.
00:12:06 Three rotors create 17,576 possible starting positions, and 60 rotor combinations mean 150 million million million possible settings.
00:12:20 But the German military Enigmas had another layer of encryption that commercial versions did not. At the front of each device was a plugboard with connections for each letter.
00:12:38 Up to 10 combinations could be made with short cables that would change the signal's value between the keyboard and the rotor mechanism.
00:12:55 For the German military to all speak the same cipher, a chart would be sent out from high command prescribing which settings should be used on a given day.
00:13:12 This was essential communication because only by sharing the same starting settings would agents be able to communicate effectively.
00:13:29 The chart included which of the five rotors to use, in which order, the starting positions of the rotors, and the 10 pairs of plugboard connections.
00:13:45 Combining all of these options takes the possible settings to an astronomical 150 million million million — the portable electromechanical encryption equivalent of a 67-bit encryption key.
00:14:03 Enigma has a practical link to early computing history, and because of the events of its time, we can directly connect Enigma and Bletchley to what we do and why we’re here.
00:14:20 It’s a remarkable object, and that’s a key word today: object.
00:14:31 Because Enigma will be our platform to explore principles of object-oriented programming (OOP).
00:14:43 A strength of OOP is how it models the real world, but objects in the real world are very different from objects in a codebase.
00:15:01 Enigma, on the other hand, is a physical device with moving parts—actual objects that each perform a part of the larger whole.
00:15:16 If the image we’re supposed to have of OOP is an object sending messages, then Enigma might as well be its mascot.
00:15:32 We can recreate this mechanism in code without abstracting our concept of an object beyond recognition because we could literally hold in our hands the pieces of an encryption algorithm.
00:15:49 So let’s go big right from the start. Two truths of software development: requirements will change, and this is good. If nothing needed to change, you probably don’t have any users.
00:16:09 We'd need to find a new job if that were the case, and we will never know less than we do right now because we don’t know how things are going to change.
00:16:25 It’s frustrating when we can’t make changes right when a new feature request comes along and we can’t deliver it to users because it would be too hard to implement.
00:16:38 That’s an awful feeling, and I don’t want to be there. But if we don’t know anything and it’s all going to change, how can we build anything at all?
00:16:49 Object-oriented design is one strategy to do just that. OOP design is about making change easier by managing dependencies.
00:17:10 So, what principles are we going to explore? The Single Responsibility Principle: we’ll gather together the things that change for the same reasons and separate those that change for different reasons.
00:17:28 Abstraction: we’ll manage the complexity of implementation by substituting a more manageable representation.
00:17:46 Encapsulation: an object's internal data should change on that object’s own terms.
00:18:02 Dependency Inversion: conventional architecture would have utility modules at a low level consumed by higher-level ones, but we will invert this thinking and increase reuse from top to bottom through interfaces.
00:18:19 And the Open-Closed Principle: an object should allow its behavior to be extended without modifying its own code.
00:18:36 All of this in service of small, simple objects sending messages. So, let’s start up the slide deck text editor with a new file: enigma_test.rb.
00:18:52 We’re going to use an abridged test-driven development technique today because we Rubyists love tests, right?
00:19:09 We know this because there is a test framework in the standard library. A MiniTest test suite is made up of Ruby classes and methods.
00:19:24 Tests we write will be defined inside a class that inherits from MiniTest::Test. We can get things moving by thinking at a high level: what does our Enigma need to do? It needs to encipher a character.
00:19:42 MiniTest is not a DSL; tests are methods in our class whose names start with the word 'test'. We initialize an instance of our Enigma class and call a cipher method, asserting that it returns a string and that this string is not the one we started with.
00:20:00 Alright, that looks like a thing. Let’s make that happen with a class and a method called cipher! We’ll invoke the test file from the command line by requiring 'minitest/autorun'.
00:20:22 MiniTest will find all the runnable subclasses and tell them to do their thing, which right now is to fail. There isn’t any code yet, so if that had passed, we would know that’s probably a bad test.
00:20:41 Let's add another test before we move on. It should encipher into a different letter for each character. We can make sure that 'A' is not the same as 'B' and that ciphering 'B' isn’t the same result.
00:21:01 Is this test going to pass? No, of course not. We’ll add an alphabet constant and a substitution key with the order of real World War II Enigma rotors.
00:21:23 By the way, we’ll make use of the rotor being an array, get the index of the message character from the alphabet, and then through that, pull a letter from the rotor. We’ll do this three times.
00:21:38 Show us the tests. Nailed it! I always say, 'Did it work? Commit!' We added an initial Enigma class with a cipher method, we made use of the test-driven development flow, and set up initial function.
00:21:54 The person in the front row really liked it; they were nodding a lot. If you need a primer on writing useful commit messages, I hear this talk is pretty good.
00:22:11 Tests are green, so let’s refactor. Red, green, refactor.
00:22:23 But this isn’t a talk about TDD even though you should watch that later. We’ve all heard of DRY: don't repeat yourself.
00:22:39 So what stands out for sure? But to make sure that we’re on the right track, we should ask ourselves: are these lines going to change for the same reason? Are they doing the same thing? Do they have the same responsibility?
00:22:55 In this case, absolutely! They’re responsible for how we convert a character into its matching integer.
00:23:08 So we gather together things that change for the same reason to create a single source of truth. We replace all of the alphabet index calls with our new method: the alphabet index.
00:23:23 Radio for backup situation: green 104 good buddy, over and out! Is there another method to extract here? What about this one?
00:23:36 This is responsible for how we change that integer back into a letter. By introducing a translate method, we create the source of truth for using the rotors.
00:23:51 If that needs to change, we can change it in one place and not three. And look—we can use the alphabet index method we just made and remove a lot of noise.
00:24:02 Now, the real test: are the tests still good? Alright, did it work? Commit! We extracted alpha index and translate into private methods.
00:24:18 We gathered lines that would change for the same reason, guided by the Single Responsibility Principle to create a single source of truth for those behaviors.
00:24:36 One benefit from extracting methods is that we get to name things, so now what the Enigma class is really up to is easier to see.
00:24:50 We can see that it’s translating, it’s ciphering—that’s what we expect the Enigma to do. But it’s also handling input.
00:25:04 So, Enigma converts letters to numbers and uses those numbers to generate a new string. Words like ‘and’ or ‘also’ used in describing our class can be a sign that it’s doing too much.
00:25:22 So let’s create a new collaborator where indexing is its purpose. If we think of the actual Enigma, maybe that’s the keyboard.
00:25:39 So brand new files, tests all set with imports, class declaration, testing that it converts a letter to an alpha index.
00:25:50 That’s behavior that we’re trying to move to the keyboard class. Some simple assertions: do the letters change the way that we would expect?
00:26:05 We’ll take advantage of the existing behavior. Simple green—back to Enigma!
00:26:17 So we’ll add the keyboard class that we just made. We’ll get rid of the alpha index method, and now translate uses the keyboard instead.
00:26:31 And we’re at a point where all the pieces should fit together again. But do our tests agree?
00:26:48 Oh, and we also have more than one test file now, so we’ll use a little Ruby command line magic to run every file that ends in _test.rb.
00:27:07 Magnificent! There’s something wrong with this Enigma though because we’re converting alpha to int and back.
00:27:25 Between each rotor, we’re not correctly following the connections through our device.
00:27:37 So how do we direct this? We use integers the entire way through, converting only at the beginning and the end.
00:27:51 This is going to remove a lot of overhead. We’re using the keyboard to only convert at once and stay at an integer until the end.
00:28:03 What do the tests say? Commit was wrong! It is so easy being green.
00:28:21 We need a lamp board to think of it!
00:28:32 So that’s the other side of the keyboard—it’s the keyboard but in reverse.
00:28:43 It’s not alphabet_index.get_integer, it’s start with an integer, get back to the letter — in the same way.
00:28:56 It's a drop-in replacement for our Enigma class. Alright, greener than now!
00:29:07 Let’s try something. I’ll say, 'Did it work?' and you’ll say, 'Commit!'
00:29:17 Okay, did it work? Commit! Nice! Some of you were paying attention, some of you weren't, but that's okay; I’ll get over it eventually.
00:29:41 Let’s try it again. Did it work? Alright, I’m not the only person that thinks this looks like a young Patton Oswalt. Am I?
00:29:55 Okay, this commit extracts alpha-int translation to classes of their own. Before this, Enigma methods contained the code that implemented the behavior, preventing flexibility and reuse.
00:30:10 We extracted self-contained functionality, replacing the specific code with a message sent to new collaborators. This abstraction makes Enigma lighter, easier to understand, and opens it to new functionalities.
00:30:27 The smaller classes offer utility and reuse to other parts of a larger system, so let’s write some more tests.
00:30:44 We're going to test that it enciphers according to the settings. The Enigma settings would be changed by the operator.
00:30:59 So that means we’ll need some rotors to test with. That’s alright—let’s say that a starting settings means new.
00:31:15 We know the rotor position, so we will assert on the precise result that we expect, and a failure is the precise result expected.
00:31:30 Here we have written no new code. We fold that up and pass in the rotors just like the test says.
00:31:46 Now we can move on to changing the cipher because the rotors aren’t created here anymore. The way that translate works also needs to get an update.
00:32:01 So we have begun replacing the literal references to arrays with an abstraction that allows this class to be much less involved in the implementation. Green, like Donatello the Ninja Turtle, not the sculptor.
00:32:17 Let’s look at translate again—some of you need to bone up on your Renaissance sculptors.
00:32:35 There is an object hiding in this class, and it’s not even hiding very well. What is an object?
00:32:51 It’s a combination of data and behavior. Here’s the data, here’s the behavior.
00:33:03 Besides, look at this method; it's a method that just calls another method by combining its arguments. Keyboard and integer arrays have made this obsolete.
00:33:21 Let's not let that object stay hidden; it deserves a day in the sun, and Enigma doesn’t need the extra implementation.
00:33:36 So we’ll test that it translates based on its key, which in the real one is a little mess of wires between the right and left sides of the rotor.
00:33:51 Here, the key is an array, and the argument to 'new' will use a simplified key rather than the whole Enigma set.
00:34:05 This is enough to have a good test; here it won’t overcomplicate it—it's only going one step.
00:34:19 But the test is still going to error, and we expected that. This is pre-recorded, after all, and we have the wrong number of arguments to 'new'.
00:34:34 Starting settings means initialize; we’ll carry that forward throughout this process. Translate means brackets—we know that from before.
00:34:50 Oh, emerald green! But Enigma is still using the old way, so let’s implement the new rotor class instead!
00:35:04 The good news is that the rotor arrays are ready arguments, but we’ll instantiate and pass in rotor instances instead.
00:35:18 Error after error instead of having Enigma send a message to itself—we have collaborators, small simple objects sending messages.
00:35:32 Enigma sends the message to each rotor in turn. Each message sent to a rotor: one, two, three.
00:35:45 You can see that here, one, two, three, translate method. Bye Felicia! Back to the whole thing being able to fit on the screen at once.
00:36:00 Oh, you just love to see it, don’t you? Did it work? Thank you.
00:36:12 This commit extracts the rotor class. The things that don’t align to Enigma’s purpose are in their own classes.
00:36:28 We’re left with a clear picture of what the Enigma class does: it orchestrates and conducts the communication between these different pieces.
00:36:46 This way, they can stay separate from each other. A rotor doesn’t have to know what comes before or after it, and Enigma doesn’t know how the work gets done.
00:37:02 That’s dependency inversion at work.
00:37:12 Okay, let’s get fancy. We’re going to test that it enciphers a phrase correctly; no longer single character strings to the command line.
00:37:27 Let’s get rid of that red. No changes to initialize, though we’re going to split the string into single characters and smoosh them back together at the end.
00:37:40 It already does one character, so we’ll call up our friend: map to do that for all characters, and that should work, right?
00:37:56 And the tests agree, so let’s go! We’re still missing some key functionality, a lot, kind of.
00:38:09 As it stands, even with the phrase, it’s still just a substitution cipher. We can’t have that. Test that no repeats in consecutive ciphers.
00:38:25 So if we cipher 'A', then cipher 'A' again, it should not return the same result twice in a row, and that shouldn’t only work for two calls to cipher—but in a phrase too.
00:38:40 Show me red! Two failures. If Enigma is our coordinator, then the rotor position doesn’t fit, so how about the rotors?
00:38:58 We want to know that the rotor can step one position but also that it’s not going to fall off the end of the key.
00:39:13 So we’ll set up the minimum amount of configuration needed to test this specific case.
00:39:24 Here we advance, advance, advance. We should prefer that our tests be straightforward.
00:39:38 Coming along and reading this test later when we’ve forgotten what we wrote shouldn’t take a lot of energy.
00:39:51 MiniTest, do you have anything to say? Gross! Position is data and internal to the rotor.
00:40:01 No accessor methods to be modified directly from the outside—not even any public API revealing that there is an instance variable.
00:40:15 Now position is part of how we calculate what index to return, and an internal variable passes the first test.
00:40:30 Okay, this is neat! Ruby has a method that moves the first index and an array to the back with an argument for how many times to rotate.
00:40:42 Also, notice: does anybody else get to see this method? No, it is private. That’s encapsulation.
00:40:58 So how did we do? Rotor is good. Okay, Enigma’s going to have to wait for another moment.
00:41:15 Remember the daily settings position needs to be configurable: settings equals initialize.
00:41:31 We set that up before, so let’s give it a default value. That way, we don’t have to update every rotor.new in the code base.
00:41:49 After a full rotation, it needs to let the next rotor in line tick over and will return a Boolean when it advances to cause a position to make a full rotation.
00:42:05 By not specifying a method tied to when we leave flexibility for future rotors to decide differently.
00:42:20 By the end of the war, there were machines with rotors that would tick over, and some Enigmas had four rotors.
00:42:38 So let's keep that flexibility and set it back to zero, so we’re not key-rotating a hundred times.
00:42:54 Right, the rotor tests pass, and we have what we need to make the Enigma tests function.
00:43:06 So back we go, like St. Andrews, we are on the green. And that is a golf reference, I apologize.
00:43:19 Let’s refactor! We can make it a little more comfortable in here by extracting some methods. We’ll search for things that change for similar reasons.
00:43:36 Those lines encipher a character—well that sounds like a method name: encipher_character.
00:43:52 What do these do? Well, they advance the rotors. Naming things isn’t hard!
00:44:07 We encapsulate Enigma’s internal mechanisms as well by making these methods private; they weren’t callable from outside the class.
00:44:27 When they weren’t methods, they shouldn’t be now. Future coders will know that these aren’t meant for reuse and aren’t tested in isolation.
00:44:43 These messages are for internal memo only. So how did we hold up?
00:44:59 Ah yes, Fair Degree! Fair Degree is the green patina on copper, like the Statue of Liberty. This is getting away from me.
00:45:26 This is fun! You’ve got to try this sometime. So this commit implements rotor stepping behavior.
00:45:44 With new behavior, Enigma is no longer a weak substitution cipher. We safeguarded the rotor’s internal data.
00:46:00 We only allow it to change via a method and without exposing how the behavior is accomplished.
00:46:15 We’re encapsulating this information; we’re also protecting rotor collaborators from the responsibility of knowing what rotors do.
00:46:30 Now when I think about the Enigma machine, it’s made up of three different high-level parts working together: the keyboard, the lamp board, and the enciphering mechanism.
00:46:46 The core of that is the rotors, but there’s more to it. There’s the mechanism that advances the rotor, there’s the reflector, and there’s the spindle that the rotors sit on.
00:47:02 So we’ll need a new, small, simple object to send messages to; we’ll call it a spindle.
00:47:19 Instead of passing the rotors to Enigma, we’ll pass the rotors into the spindle, and the spindle to Enigma.
00:47:32 This test causes the first rotor to complete a full turn, and we’re asserting that the second rotor got the signal.
00:47:45 Yeah, that was never going to work. Navy Enigmas used four rotors at a time whereas Army and Air Force used three.
00:47:59 If it’s not hardcoded, ours will have that same flexibility. Look familiar? That’s the body of the ‘do map’ from the Enigma class.
00:48:13 We don’t know how many rotors we’ll iterate with my favorite enumerable method: reduce.
00:48:29 Have you been introduced to reduce? Reduce iterates the array; each iteration gives us the current object and the return value of the previous iteration.
00:48:43 But the first iteration gets the argument; it’s the same game to advance the rotor.
00:48:59 Except that if the step signal is true, the rotor advances and sends its step signal down the line. We start with true so that the first rotor always advances.
00:49:14 If the rotor does advance and it returns true, the step signal will be true for the next rotor in sequence.
00:49:31 Also, please don’t use a do-end here unless you are also running out of room on your slides.
00:49:46 Oh, we are so green! We get mistaken for the Incredible Hulk! Oh, got me!
00:50:00 I was using that as a rhetorical device to summarize when we finished the topic.
00:50:16 So hang on—back in Enigma, the rotors are no longer Enigma’s responsibility anymore, which means that this isn’t either.
00:50:32 We’ve got breathing room to open Cipher; we’re abstracting so well.
00:50:47 We’re abstracting away the class dependencies, so we’re only responsible for the idea of what this class is: a transformer.
00:51:02 If someone wants to use this class, they don’t even have to use a spindle; the modules are loosely coupled.
00:51:17 Whole new functionality doesn’t need to change code in this file. We know less now than we ever will; but because of OOP design, it doesn’t even matter.
00:51:32 Just pass in a different transformer! You want to use elliptic curve cryptography? Go right ahead!
00:51:48 You want to use MD5? 1993 called, and they want their algorithm back. But you can! I’m excited; are you excited?
00:52:02 Green, green, green! Like, I don’t know, all the little dots in the terminal.
00:52:15 I’ll be with you in a second. Hit me baby one more time! Did it work?
00:52:29 Thank you! This commit abstracts everything away from Enigma’s responsibility.
00:52:47 Enigma is open for extension and closed for modification, enabling painless reuse in ways that we don’t even have to try and predict.
00:53:02 Led by OOP design principles, we’ve built an Enigma replica that is easy and fun to work with using tech and ideas that stand on the shoulders of giants like Alan Turing, John von Neumann, Grace Hopper.
00:53:19 And you can hear him. Matoto! What a ride!
00:53:35 Single responsibility: objects and methods that strive for a cohesive unified purpose.
00:53:50 Abstraction: relocating implementation and replacing it with a simpler, easier-to-reason-about representation.
00:54:05 Encapsulation: an object should respond, react, and update on its own terms.
00:54:18 Dependency inversion: higher-level objects operate without being involved in the specifics of those that they send messages to.
00:54:29 Open for extension and closed for modification, because you don’t even need to.
00:54:44 It’s all in service of small, simple objects sending messages, because change is hard—but it doesn’t have to be.
00:55:17 If you want to chat more about features to implement with Enigma, we didn’t even get to the reflector, the plugboard, or a lamp board that could return HTML instead of a string.
00:55:31 Or a keyboard that’s actually an API endpoint! Or maybe you too have feelings about how Turing was murdered by his own government.
00:55:48 Or maybe you want to chat about Bletchley Park or like object orientation. I’m going to be hanging around the Thoughtbot booth a lot tomorrow, so come by and say hi. Thanks again.