Booleans are Easy - True or False?
This is a modal window.
Das Video konnte nicht geladen werden, da entweder ein Server- oder Netzwerkfehler auftrat oder das Format nicht unterstützt wird.
Formale Metadaten
Titel |
| |
Serientitel | ||
Anzahl der Teile | 88 | |
Autor | ||
Lizenz | CC-Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Unported: Sie dürfen das Werk bzw. den Inhalt zu jedem legalen und nicht-kommerziellen Zweck nutzen, verändern und in unveränderter oder veränderter Form vervielfältigen, verbreiten und öffentlich zugänglich machen, sofern Sie den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen und das Werk bzw. diesen Inhalt auch in veränderter Form nur unter den Bedingungen dieser Lizenz weitergeben. | |
Identifikatoren | 10.5446/37278 (DOI) | |
Herausgeber | ||
Erscheinungsjahr | ||
Sprache | ||
Produzent | ||
Produktionsjahr | 2018 | |
Produktionsort | Pittsburgh |
Inhaltliche Metadaten
Fachgebiet | ||
Genre | ||
Abstract |
|
RailsConf 201877 / 88
9
14
16
19
20
22
23
26
27
28
34
35
36
37
38
39
41
42
46
47
53
57
60
62
63
64
69
72
80
85
87
00:00
SchaltfunktionRechenschieberRechenschieberCoxeter-GruppeSchaltfunktionTwitter <Softwareplattform>Rechter WinkelDiagramm
00:40
PrimzahlzwillingeSchreib-Lese-KopfProgrammiersprache
01:07
DifferenteBitSchaltfunktionComputeranimation
01:38
Boolesche FunktionParametersystemMenütechnikRechenwerkBewegungsunschärfeZeichenketteVariableWeg <Topologie>Konfiguration <Informatik>Objekt <Kategorie>Einfache GenauigkeitObjekt <Kategorie>Boolesche FunktionFehlermeldungKlasse <Mathematik>EmulatorHash-AlgorithmusVererbungshierarchieKonfiguration <Informatik>SchaltfunktionSpeicherabzugParametersystemZeichenketteDeskriptive StatistikNormalvektorZweiInstantiierungStrömungsrichtungProgrammfehlerCodeExogene VariableAssoziativgesetzTermEinfache GenauigkeitProgrammierspracheVerschlingungSoftwaretestZeiger <Informatik>ErwartungswertInverser LimesVariableVerkehrsinformationArithmetischer AusdruckKontextbezogenes SystemTouchscreenFormale SpracheMultiplikationsoperatorClientMailing-ListeQuick-SortComputeranimationVorlesung/Konferenz
09:18
Data DictionaryProdukt <Mathematik>MultiplikationMultiplikationsoperatorWort <Informatik>Neuroinformatik
09:42
Objekt <Kategorie>ProgrammierungArithmetisches MittelGeheimnisprinzipProgrammiergerätObjektorientierte ProgrammierspracheObjekt <Kategorie>VerschlingungCoxeter-GruppeWeb Site
10:26
EinflussgrößePhysikalisches SystemSoftwareKomponente <Software>Objektorientierte ProgrammierspracheZusammenhängender GraphEinflussgrößeObjekt <Kategorie>Physikalisches SystemSoftwareVorlesung/Konferenz
10:53
Physikalisches SystemDatentypOrtsoperatorAlgorithmusPlastikkarteZahlenbereichDienst <Informatik>Große VereinheitlichungValiditätGemeinsamer SpeicherMathematikPhysikalisches SystemParametersystemBildschirmmaskeElektronische PublikationProgrammierungCodeSchlussregelArithmetisches MittelGüte der AnpassungUmwandlungsenthalpieDifferenteNeuroinformatikEinsTypentheorieDynamisches SystemKonditionszahlMailing-ListeProgrammierspracheMereologieHydrostatikOrdnung <Mathematik>SoftwareAbgeschlossene MengeInterpretiererOrtsoperatorObjekt <Kategorie>PasswortApp <Programm>AlgorithmusDatenbankCodierung <Programmierung>Boolesche FunktionVorlesung/Konferenz
14:34
AggregatzustandBoolesche FunktionFehlermeldungRechenwerkMenütechnikVakuumSLAM-VerfahrenAggregatzustandBoolesche FunktionZeichenketteDatenfeldENUMCASE <Informatik>Befehl <Informatik>Klasse <Mathematik>Elektronische PublikationSchaltnetzCodeVolumenvisualisierungObjekt <Kategorie>GrenzschichtablösungZustandsmaschineKonfiguration <Informatik>Ordnung <Mathematik>ProgrammfehlerDatensatzFehlermeldungTexteditorXML
17:11
FehlermeldungVersionsverwaltungCodeZeichenketteBenutzerbeteiligungWort <Informatik>Klasse <Mathematik>PermutationZahlenbereichURLFormale SpracheSymboltabelleBoolesche FunktionTypentheoriePunkt
18:17
Boolesche FunktionDatenfeldVarianzAttributierte GrammatikSchmelze <Betrieb>CAN-BusFehlermeldungE-FunktionBeschreibungskomplexitätMUDVolumenvisualisierungDatenfeldBoolesche FunktionAggregatzustandCASE <Informatik>ÄhnlichkeitsgeometrieZahlenbereichVariableGeradePotenz <Mathematik>CodeAbfrageSoftwaretestWeg <Topologie>Konfiguration <Informatik>MultiplikationsoperatorBoolesche AlgebraTouchscreenDatensatzObjekt <Kategorie>Leistung <Physik>Komplex <Algebra>Ausdruck <Logik>Konditionszahl
20:44
Boolesche FunktionOperations ResearchSpieltheorieAlgebraisches ModellInverter <Schaltung>VerknüpfungsgliedNichtlinearer OperatorÄquivalenzklasseBoolesche AlgebraNichtlinearer OperatorBoolesche FunktionSymboltabelleVorzeichen <Mathematik>BinärcodeMathematische LogikMultiplikationsoperatorMathematikZahlensystemQuadratzahlQuick-SortTelekommunikationGeradeEin-AusgabeFunktion <Mathematik>MereologieKreisflächeSchnittmengeSymmetriePunktBitVerknüpfungsgliedRechenschieberEinfache GenauigkeitNegative ZahlEinsWahrheitstabelleElement <Gruppentheorie>DigitaltechnikKonfiguration <Informatik>Delisches ProblemKnotenmengeComputeranimation
25:11
Boolesche FunktionTransformation <Mathematik>Prädikat <Logik>MarketinginformationssystemLokales MinimumGesetz <Physik>Gesetz <Physik>Boolesche FunktionSchnittmengeArithmetischer AusdruckTelekommunikationTransformation <Mathematik>Zusammenhängender GraphEin-AusgabeCodePunktPrädikat <Logik>Data MiningInverter <Schaltung>Nichtlinearer OperatorRechter WinkelTermComputeranimation
27:53
Prädikat <Logik>GeradeSoftwaretestSchlussregelGesetz <Physik>Schreib-Lese-KopfIdentitätsverwaltungTermMultiplikationsoperatorPunktVorlesung/Konferenz
29:35
Prädikat <Logik>PunktAuswahlaxiomSchaltfunktionBoolesche FunktionQuellcodeRückkopplungTwitter <Softwareplattform>E-MailRechenschieberArithmetisches MittelSchaltfunktionWeb-DesignerQuellcodeRechenschieberE-MailCodeMultiplikationsoperatorLesen <Datenverarbeitung>AbstraktionsebeneStellenringGruppenoperationOrtsoperatorPunktBoolesche FunktionOffene MengeBitUmsetzung <Informatik>Coxeter-GruppeVorlesung/KonferenzComputeranimation
31:55
COMp-BlockDatentypXMLComputeranimation
Transkript: Englisch(automatisch erzeugt)
00:13
My name's Craig Buchek, and I'm gonna talk to you about Booleans today.
00:20
If you wanna follow along, I've got slides up here. In the lower right corner, you can get to it if you need to get to it later. I do have some references and some more details, things I won't talk about in the presenter notes. You can just hit P to toggle those if you're playing along or playing along later. My Twitter's in the upper right corner if you wanna tweet at me or about me.
00:41
I live in St. Louis, and that means I get to go to a conference called Strange Loop without having to pay for any travel. And I went last year, and it's a great conference. Lots of things over your head there, though, but it's really inspirational. My favorite talk was actually the pre-conference day
01:01
at Elm Conf. Elm is a programming language that compiles down to JavaScript. So I went to that, and it was a talk on Booleans by Jeremy Fairbank. And that talk actually inspired me to create this talk. I thought, how is he gonna talk 40 minutes about Booleans? Turns out that's really hard.
01:21
My talk's probably gonna be closer to 30 minutes than 40. So that talk really inspired me. It was my favorite talk. But Ruby's very different than Elm, so this talk is gonna be quite a bit different than Jeremy's, but I'd recommend watching Jeremy's as well. So, on to Ruby.
01:41
Booleans are pretty simple, right? Things are either true or false. True and false are instances of the true class and the false class. See there? In fact, there's really only one instance of each. No matter how we get to true, it's always the same object.
02:01
If you use the object ID method there, you get 20 for all trues. All falses happen to be zero. Oddly, you can't create a new instance of these classes, which kind of makes sense, because if there's only one of them, you don't want to create a second one of each of those.
02:20
So you get no method error on true class new or false class new. Interestingly, there's no Boolean class in Ruby. Try to pull up Boolean and it doesn't know what that is. If you look at true class, it has no ancestors that are Boolean. Just object, kernel, and basic object. Just pretty much any object's gonna have
02:41
those same ancestors. Apparently this is due to Ruby's small talk heritage. I suppose it's because it's dynamically typed. You'd never have a reason to declare a variable as a Boolean. So anywhere Ruby expects a Boolean, you can actually use any object. So you can basically, if you want to treat something true,
03:04
you can pass 123 or a new object. There's only two things that are treated as false. Those are false and nil. See the bottom two there. You might hear the terms truthy and falsy. They express something that Ruby will interpret as true or false in a Boolean context.
03:24
You might come across those terms in RSpec test. Expect 123 to be truthy and you might expect something that returns false or nil to be falsy. I wouldn't recommend doing that in if statements though.
03:41
You're better off to use something idiomatic. Something intention revealing that returns a Boolean. Here we're checking to see if the string is empty or blank and if the variable's a nil. This isn't really as big a problem in Ruby as in other languages. It's like Perl, PHP, JavaScript interprets the empty string and zero is false.
04:01
I think that leads to a lot of errors. I think that's probably the second largest programming language mistake ever made. There's something called the billion dollar mistake that Tony Hoare made. He said when he introduced the null pointers, he thinks that led to over a billion dollars of damage to the industry.
04:24
So next we're gonna talk about Booleans used as parameters in methods. So I spend a lot of time in the Rails console or IRB or in Pry when I'm debugging some tests or whatever. Often I'll wanna see the class of an object. So you can just do object name dot class
04:44
and often I'll wanna see what methods that object responds to. I'll use a method that's on object name methods or a method that's on class name instance methods. And you can see I'm using those two methods up there. They return the same thing. Notice those usually return a long list of methods.
05:03
Here they're running off the right side of the screen. Show of hands, who's familiar with either of these methods? All right, those with your hands up, do you know they take an optional parameter? A lot fewer, like three I think. And those of you who remain with your hands up,
05:21
how many remember whether you're supposed to pass true or false to not show the methods of the super class? One hand left, all right. It happens to be false for these methods. But I can never remember that. I always have to look at the documentation or more likely I just trial and error and see which one it takes.
05:42
So to use it properly, you have to remember do I pass it true or do I pass it false? So is there a way we could do better? Now those are built in methods and so this is sort of just a theoretical thing. The best way to fix this API is to use a name parameter to describe the parameter. It'd be nice if I could just say instead of methods false,
06:01
I could say methods super class methods false to not show the super class methods. But this method predates name parameters in Ruby and we need to keep backwards compatibility. So in older Ruby versions, we used to have to use an options hash to emulate name parameters
06:20
and since we want this to be backwards compatible, I would still have to do that. Also to take either a bare boolean or a hash would have to use this method. So I actually wrote a replacement methods method that gives us the option to either use the old way, passing false, or to use that
06:42
named super class methods option. Maybe I'll submit that to the Ruby core team. But ideally it'd probably be better just to have two separate methods. One called methods that gives you just the immediate methods and one called all methods that gives you everything.
07:06
So how would you describe what that original method does? I would say that it shows the methods defined for this object or the methods only defined by its immediate class. Anytime you have an or in a description of a method or class that's a code smell
07:21
and you're probably violating the single responsibility principle. Came across this example from Rails a couple months ago when I was upgrading to Rails 5. So these both do the same thing. The first one was the original Rails API. I don't know how far back it goes.
07:40
So user's an object and it has an association called things. Normally you just say user.things and it'll give you all the things that that user owns. But if you want it to reload you pass true to things. Second is the current API, user.things.reload. It's more explicit. Again, what does that true mean there?
08:01
The original API was deprecated as of Rails 5 and removed as of Rails 5.1. So not only is the new one clear but the old way can lead to some very subtle bugs. So I found this bug. This is Rails issue 26413. Actually I have a link to that if you want to check it out.
08:21
So the bug report complains that the sales are being reloaded. And he's like why are the sales being reloaded here? Anyone see the issue here? Right, so the problem is that the sales association doesn't actually take a hash. It takes a boolean like the previous screen. So the true there.
08:43
So as I said before, anything besides nil and false are treated as true. So that limit 10 which desugars to a hash is interpreted as true. So it's just client sales true. And so it's reloading the sales and it's not doing any limiting.
09:02
You'd have to do sales.limit parenthesis 10 to get it to work. Or maybe you could do where. I don't think you can do a where with limit. So very subtle. You can't really see why that's a bug. So I want to take a short detour here
09:20
to talk about something called kinescence. Kinescence was a word that existed before computers were around. These are some definitions from Webster's Dictionary as far back as 1913. Kinescence means common birth or production of multiple things at the same time or the act of growing together.
09:43
So 1992, a person named May Lear Page-Jones brought this idea to the object oriented program community. First it was in a paper comparing techniques by means of encapsulation and kinescence. Then he wrote a good book, or a book that I've heard is pretty good. I'm going to pick it up sometime.
10:01
1996, What Every Programmer Should Know About Object Oriented Design. And then he had a follow up when UML was all the rage in 1999, Fundamentals of Object Oriented Design in UML. So he talked about kinescence. I've got links to those in the presentation notes including the full text of the original article from the ACM.
10:21
There's a couple other sites. Kinescence.io is pretty good about explaining this pretty well too. So here's May Lear's definition of kinescence. It's a measurement of the amount of coupling or dependencies among components within a software system. And in particular, he's talking about an object oriented system.
10:43
So 2009, Jim Weirich brought this idea of kinescence to the Ruby community. Unfortunately, Jim passed away a few years ago. He is definitely missed at conferences. So here's roughly Jim's definition of kinescence. Two pieces of code share kinescence when changing one requires
11:01
a corresponding change to the other. And if you have excessive kinescence, it means the system's hard to change and hard to maintain. So Jim gave a few different talks on this. The first one was called the Grand Unified Theory of Software Design. He had an example very similar to my methods example.
11:20
And in 2012, he had a newer talk called Kinescence Examined. So Jim made the argument that kinescence underlines many of the other rules of good object oriented design like dry and code smells and race conditions. So we wanna reduce kinescence like we wanna reduce coupling.
11:42
Here's a list of different types of kinescence. They're ordered from weakest to strongest, so we should prefer the ones towards the top. These are the static kinescence types. There's some dynamic types as well, but they're all stronger than these, so you'd prefer to use the static versus the dynamic.
12:02
So I'll go through each of these. Kinescence of name means agreeing on the name of something in two different parts of your code. So an example, anytime we call a method, the method name that we used to call it has to be the same as the method name that we used to define it. And it's the same with any variable or constant. When we reference it, it has to be the same name.
12:22
That's pretty common, right? Kinescence of type is agreement on the type of something. Now we don't have static types in Ruby. We have what's called duck typing, which means does it quack like a duck? If it quacks like a duck, then it's acting like a duck. It's close enough. Kinescence of meaning is agreement
12:41
on the meaning of the interpretation of specific values, like true or false. Kinescence of position is agreement on the order of values, like if you have a method that takes three arguments, the order that you specify them is important. Although if you use name parameters, we go up to kinescence of name.
13:03
So according to this, you should always use name parameters. I don't know if that makes sense, but I'm actually thinking about that. Kinescence of algorithm is probably one of the more interesting ones on this list. Agreeing on a particular algorithm. And the two examples that I came up with are encoding and decoding passwords.
13:21
You have to have, if you've got two different apps using the same database with encoded passwords, you have to use the same algorithm. The other one is credit card numbers. There's a checksum to make sure that your credit card number is a valid credit card number. And so you might have client-side code, server-side code, and then a service
13:41
that all have to run that same algorithm to run checksum on the card number. So remember, we always want to reduce kinescence. If we can replace a stronger form with a weaker form, we've reduced kinescence. One way to do that is increased locality. So if you've got two things in the same file
14:01
that have the same name or the same meaning, it's easier to understand than if it's in a different file or in a different program like that credit card example. They're on different computers written in different programming languages. So note that kinescence of name is weaker than kinescence of meaning, and that's what we did here. We replaced the boolean parameter
14:20
with a specific meaning with a name parameter, and that specific meaning is difficult to remember. And we reduced kinescence by replacing kinescence of meaning with kinescence of name. So next I want to talk about booleans used to represent application state.
14:44
That's a picture of the Balkan states, by the way. Let's say we have an editor class and it has several booleans representing possible states. We might need to keep track of whether the user's editing if the file is being saved or if there's an error condition.
15:01
Anyone see a problem with this class? All right, the problem is we can end up in a combination of states that make no sense. What do we mean to be both editing and saving? Well, if the error is true, then do the other fields actually make any sense? We should try to ensure our code can never get into an impossible state. There's a great talk by Richard Feldman,
15:22
again, it's in Elm, but it's probably still worth watching, called Making Impossible States Impossible. So how can we improve on that? We should use a single field to represent the state. This doesn't look like a big improvement. We still have the case statement there, but it does prevent us from ever getting
15:40
into a state that's meaningless or invalid, and ensures the options in our case statement, the order of those options doesn't really matter in a case statement. We can do better than that, though. Active record enum is something that was added, I think Rails 4, maybe 5, I think it was 4,
16:02
to define possible states. This allows us to catch bugs easier because Ruby will catch an incorrect method name more easily than a mistyped symbol or string. If you see here, we've got state.editing question mark. So any of the states that we define up there,
16:21
editing, saving, and error, we get methods with question marks in there that we can just check them. There's several state machine gems. We could implement our own to create a state object. The gems usually have some other nice features that are helpful. Although the enum is pretty nice,
16:42
it came out after the state gems. If you can use enum, I would recommend that first and then look into some of the state machine gems. The state class is pretty similar to the enum here in this example, except if we have a sufficiently specialized state class, maybe we can just delegate to the object itself
17:02
and have it render, so a state could do the render for us. The original version of that code contains a code smell called primitive obsession.
17:22
It's using a primitive type when a more specialized type would be more appropriate. Usually that's gonna be a class in Ruby, of course. So one example is using floating point numbers to represent money. Another is using a string to represent a URL. If you think about it, a URL has more than
17:40
just a string of text, it actually has pieces. It has the name of the web server, it has a path, it's got fragments, it's got a query string. So using a string isn't always the best idea there. So in Ruby, we're apt to actually abuse strings in this way, it's often called stringly type
18:00
to play on words from strongly typed from other languages. But this is an example where we overuse booleans. This version still has primitive obsession. We just replaced boolean permutives with symbol permutives. Next I'm gonna talk about boolean fields.
18:22
We've got a boolean attribute here to keep track of whether the object has been deleted. I used a little tool there I wrote called the Virtus Active Record so I can show you in the code what attributes the model has. So we've got a deleted field that's a boolean. And it just says, has this been deleted?
18:41
We can have a query to show just not deleted users. So my suggestion, instead of marking something that's deleted with a boolean, we can mark when it was deleted. This turns out to be pretty useful in the end.
19:02
And we might wanna keep track of who and when it was deleted. Auditing, you probably wanna know who did things and when they did them. Next we'll talk about exponential complexity with booleans.
19:24
Let's say we have a method to render the document taking each of those three boolean options again. But this time let's say the states are actually independent of each other and we can't combine them. So how many cases would we have to handle if this method takes three booleans there? It's gonna take eight.
19:42
So eight cases for three independent boolean variables. If you're lucky you'll get to write it like this. If you're unlucky it's gonna look more like that. That's a method with 29 lines of code. Too big to fit on the screen here. That's without doing anything interesting. We're just calling another method for each case.
20:02
Don't forget the eight test cases you're gonna need. More likely than not you're probably gonna forget one. And you're not gonna have any protection really from forgetting it. So the formula for the number of conditions is two to the power of n if you have n independent boolean variables.
20:21
That's exponential growth of the bad kind. So our solution here again is to represent the state with a single variable just passing the state. Now we only have to handle one case for each possible state. Now we're down to three or four cases. Four if you wanna handle the missing case.
20:41
And a similar number of tests. So let's move on to boolean operations and boolean algebra. This won't be too bad. Let's start out pretty simple. So there's this little square corner sign
21:01
that's the boolean algebra symbol for not. In Ruby we use the exclamation point frequently called bang in Ruby. I think that came from Perl perhaps. Sometimes you'll see a squiggle or a tilde. And a lot of times in mathematical notation or I guess sort of electronics notation
21:21
you'll see an overline. A line over a variable or whatever is being used to represent the boolean value. Note that Ruby does have the tilde operator but that's for, it's rarely what you want. It's used for binaries not for booleans.
21:42
So not false is true and not true is false. So this is called the truth table. This is one for negation. So if you've got x of zero then not x is one and vice versa. So we often think of true and false as one and zero
22:01
or on and off. Comes from electronics. In fact electronics has their own symbols for this. So that's the not symbol. The important part is actually the circle there on the right side. So that says whatever input comes in on a the opposite output will go out on q.
22:21
So the and, the fancy word for and is conjunction. In boolean algebra it's like a carrot symbol or an inverted v. That's called the conjunction symbol. If you remember sets, intersection is upside down u. Kind of the same thing.
22:42
The intersection is things that can items from one set and the other set. So there's actually a symmetry between sets and booleans. In Ruby we use ampersand ampersand. You may see multiplication signs.
23:02
I'll talk about that in a bit. Ruby also has a single ampersand for, again that's for binary and. And there's also the and keyword but you probably don't want to use it because it has a different precedence. If you use RuboCop it pretty much tells you never to use it. So stay away from that unless you really know what you're doing.
23:22
So here's the truth table for and. On that last slide I showed that multiplication sign is an alternative notation. If you look at that, if you treat them as zeros and ones you multiply them and you get the answer there for the and. I did not know that.
23:41
Here for electronics is the logic gate for and. The fancy word for or is disjunction. So Boolean algebra, that v-like symbol is called the disjunction symbol. Again like sets, it looks very much like the union symbol and union is something is about elements
24:03
belonging to one set or the other. In Ruby we use the two vertical bars. Again we also have the single bar for binary and we have the or keyword but rarely do you want to use either one of those. Sometimes you'll see a plus sign. So there's some of the options
24:21
using Ruby double vertical bars. Here is the truth table. So again, addition, if you just put a plus sign between those two, the first three make sense and the last one, one plus one is one? Well there's no twos in binary
24:41
so I think you just have to memorize that one. An or gate in logic symbols or digital logic. A couple other operators you might run into, exclusive or, I rarely have seen that symbol. I haven't really seen the symbols for the other two either.
25:02
There's actually 16 possible operators of two Boolean operands but most of them aren't very interesting like the one that always returns true. There's a set of laws that govern transforming Boolean expressions.
25:22
A friend of mine came across something like this once and he submitted a pull request to make it clear. So we've got a predicate method. A predicate method just means a method that returns true or false. And it's based on two other predicate methods here. Having that explicit true or an explicit false is kind of a smell to me.
25:41
With possible exception if you've got a guard clause that's returning true or false early in a predicate method. We're gonna need some tools to refactor that to make it more readable. So here's some of the ways you can transform Boolean expressions. We can use these to refactor or simplify our code. Note these come in pairs, one for and and one for or.
26:03
It's a lot of transformations for just two possible values and three operators, right? There's actually more than that. One more thing I wanna point out, Ruby has short cutting which means that different code might run depending on which is on the right and which is on the left.
26:21
But the value you'll get back will be the same either way. So I wanna call one of those out in particular called De Morgan's Law. This basically shows you can switch and and or by adding nots if you see there in the top one. The second set there is just the first set with the side switched and the nots
26:42
moved to the other side. So really we only need not and either and and or and we can replace one with the other if we need to. We can rewrite the third operation in terms of the other two. For clarity's sake I would encourage you not to do that in most cases.
27:01
Electronics actually goes further and they only have a component called the NAND gate which does an and not. For a not they just use a single input that goes into both inputs and it just nots it. But for our purposes we can use De Morgan's Law to clarify our code.
27:23
One other transformation is taking an if then else and converting it to use Boolean operators. I had to look that one up and check it out and make sure I got it right. So basically if you read the right side it reads pretty close to the same.
27:40
So if X and Y, X then do Y and if that's not true then check X again and otherwise do Z. So now that we've got the proper tools let's get to work. That explicit true sticks out to me
28:00
but it's easier to get rid of the if first. And I wrote the rule down there that we're gonna use. So we apply that rule and we got rid of the if statement. Now we've got some duplication there. As Sandy Metz says, sometimes you need to take a step back to get to where you're headed. So we can use the identity law now
28:21
to get rid of that explicit true on the right side. Now we can use distributed law to put those two together or to put the two approvers enabled next to each other. Now we have what's called a tautology. X or not X, that's always gonna be true, right? So we're gonna get rid of the second line there,
28:43
line three, that's gonna be true. We can get rid of true with the identity law again. Anything and true is that same thing. So now we've got just two terms and we can go one of two ways at this point. We could apply De Morgan's law
29:01
but I don't think that's any easier to read than the last one. I would actually go with this to refactor and extract some methods to make things more clear. So don't be afraid to extract a method even if it's just one line and even if you're adding just a not if it's going to make things more clear
29:22
even if they're used in just that one place. Note that I did a lot of small steps there, right? And typically I do more than one step at a time but man, you really wanna have tests that you don't mess things up. Oh, what did I just hit?
29:41
All right, so the question is which of these would you rather come across? Which is easier to figure out the meaning of? I would say the second one is easier to read, easier to understand, easier to change than the first one. So what's the point of this?
30:01
The original code that we looked at all worked. So why would we change it? We read code a lot more than we write it so we should optimize for reading and more importantly we should optimize for understanding. Abstractions are meant to help us understand things. As Sandy Metz says, take the time to find the right abstraction.
30:21
Sometimes that'll take some extra work. Writing good code will take longer in the short run but in the long run it'll pay off. So I hope that I've shown that there's more to Booleans than meets the eye but the bigger point is we can make our code easier to read and understand. So take a little time to make it easier for the next person who has to read your code.
30:42
More often than not that'll be you. And even if it's not, it's the right thing to help your teammates out. So thanks for coming. Thanks to Jeremy Fairbank for inspiring this talk. Amos King who provided some of the examples. My local user group in St. Louis. My team at F5 and RailsConf for choosing my talk.
31:05
And thank you to my employer F5 who sponsored my travel. We do have a few positions open for web developers. If you're interested you can come see me. So a coworker told me this joke and it's the only joke I could find about Booleans. Best thing about a Boolean is even if you're wrong
31:21
you're only off by a bit. I don't know if that's that funny. So one reason I give talks at conferences is to start conversations. Please don't hesitate to come and talk to me. And you can find the slides there, the source.
31:40
I used a tool called Remark to create these slides in HTML. You can tweet at me, check out my GitHub. Check out the presentations on GitHub or send me an email. Thanks for your time.