Composite Validators – Refined

I recently saw a post on how to compose different validators together. I thought it was a good start, but I think it didn’t go quite far enough, especially using the fact that Rob Napier has so kindly reminded us about Swift: types are the unit of composition in Swift.

Here’s the basic setup: there is a need to create some basic validation for email and passwords (the correctness of the validation rules is not important to the discussion).

Scott modeled out what how he conceptually thought of each, which I thought was good. I’ve put those models here, with only some minor name changes:

Email Validation
                ┌────────────────────────┐                
                │    email validation    │                
                └────────────────────────┘                
                             ▲                            
             ┌───────────────┴───────────────┐            
┌────────────────────────┐      ┌────────────────────────┐
│         empty          │      │     invalid format     │
└────────────────────────┘      └────────────────────────┘
Password Validation
                ┌────────────────────────┐          
                │  password validation   │                               
                └────────────────────────┘                               
                             ▲                                           
             ┌───────────────┴───────────────┐                           
┌────────────────────────┐      ┌────────────────────────┐               
│         empty          │      │          weak          │               
└────────────────────────┘      └────────────────────────┘               
                                             ▲                           
                                             │ ┌────────────────────────┐
                                             ├─│         length         │
                                             │ └────────────────────────┘
                                             │ ┌────────────────────────┐
                                             ├─│   missing uppercase    │
                                             │ └────────────────────────┘
                                             │ ┌────────────────────────┐
                                             ├─│   missing lowercase    │
                                             │ └────────────────────────┘
                                             │ ┌────────────────────────┐
                                             └─│     missing number     │
                                               └────────────────────────┘

I think these are conceptually good. However, I wasn’t a fan of how Scott transcribed these models over to their enum representations.

Scott’s Version
enum EmailValidatorError: Error {
    case empty
    case invalidFormat
}

enum PasswordValidatorError: Error {
    case empty
    case tooShort
    case noUppercaseLetter
    case noLowercaseLetter
    case noNumber
}

I think the PasswordValidationError missed the mark as he flattened out the tree.

My Version
enum EmailValidationError: Error {
	case empty
	case invalidFormat
}

enum PasswordValidationError: Error {
	case empty
	case weak(reasoning: [PasswordStrengthValidationError])
}

enum PasswordStrengthValidationError: Error {
	case length
	case missingUppercase
	case missingLowercase
	case missingNumber
}

I break out the weak items into their own PasswordStrengthValidationError error enum to match the conceptual model. This has the benefit of provide a high-level classification of “weak password” while still maintaining the rigor of getting the specific details about why the password is considered weak.

Validation

Next up is the modeling of the validator itself. I like that Scott chose to model this as a protocol. After all, we do know that we are going to need two different types of protocols:

  1. Single validation
  2. Composite validation

However, unlike Scott, I would have modeled both of these with a protocol, like so:

protocol Validator {
	func validate(_ value: String) -> Result
}

protocol CompositeValidator: Validator {
	var validators: [Validator] { get }
	func validate(_ value: String) -> [Result]
}

Side note: I’m also use a more generic Result type vs. Scott’s ValidationResult. It’s simply defined as:

enum Result {
	case ok(ValueType)
	case error(Error)
}

The important thing to note about the CompositeValidator is that it supports returning both a single result and a listing of all of the results. The other nice thing about this is that it’s also possible to provide a default implementation for all implementors of this protocol.

extension CompositeValidator {
	func validate(_ value: String) -> [Result] {
		return validators.map { $0.validate(value) }
	}

	func validate(_ value: String) -> Result {
		let results: [Result] = validate(value)
		let errors = results.filter {
			if case .error(_) = $0 {
				return true
			}
			else {
				return false
			}
		}

		return errors.first ?? .ok(value)
	}
}

In the single result case, we simply return the first error value, if present, or return the ok value. This default implementation will come in really handy when we start implementing things later on.

Types as the Foundation

Remember that types are the foundation? So yeah… let’s start implementing the email validators as they are the most straight-forward of the two.

class EmailEmptyValidator: Validator {
	func validate(_ value: String) -> Result {
		return value.isEmpty ? .error(EmailValidationError.empty) : .ok(value)
	}
}

class EmailFormatValidator: Validator {
	func validate(_ value: String) -> Result {
		let magicEmailRegexStolenFromTheInternet = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"

		let emailTest = NSPredicate(format:"SELF MATCHES %@", magicEmailRegexStolenFromTheInternet)

		return emailTest.evaluate(with: value) ?
			.ok(value) :
			.error(EmailValidationError.invalidFormat)
	}
}

The single value ones are fairly straight forward – you just implement the logic in the validate function based on the value passed in.

Now, to compose the email validations, all we need to do is this:

class EmailValidator: CompositeValidator {
	let validators: [Validator]

	init() {
		self.validators = [
			EmailEmptyValidator(),
			EmailFormatValidator()
		]
	}
}

That’s it! No extra code to worry about as the default CompositeValidator extensions handle this correctly.

The usage code looks like this:

let emailValidator = EmailValidator()
validate(value: "", validator: emailValidator)
validate(value: "invalidEmail@", validator: emailValidator)
validate(value: "validEmail@validDomain.com", validator: emailValidator)

Which will output:

value: "" => error(EmailValidationError.empty)
value: "invalidEmail@" => error(EmailValidationError.invalidFormat)
value: "validEmail@validDomain.com" => ok("validEmail@validDomain.com")

Password Validation

The single value password validators are all straight forward to implement:

class PasswordEmptyValidator: Validator {
	func validate(_ value: String) -> Result {
		return value.isEmpty ? .error(PasswordValidationError.empty) : .ok(value)
	}
}

class PasswordLengthValidator: Validator {
	static let minimumPasswordLength: Int = 8

	func validate(_ value: String) -> Result {
		return value.characters.count >= PasswordLengthValidator.minimumPasswordLength ?
			.ok(value) :
			.error(PasswordStrengthValidationError.length)
	}
}

class PasswordIncludesUppercaseValidator: Validator {
	func validate(_ value: String) -> Result {
		return value.rangeOfCharacter(from: NSCharacterSet.uppercaseLetters) != nil ?
			.ok(value) :
			.error(PasswordStrengthValidationError.missingUppercase)
	}
}

class PasswordIncludesLowercaseValidator: Validator {
	func validate(_ value: String) -> Result {
		return value.rangeOfCharacter(from: NSCharacterSet.lowercaseLetters) != nil ?
			.ok(value) :
			.error(PasswordStrengthValidationError.missingLowercase)
	}
}

class PasswordIncludesNumbersValidator: Validator {
	func validate(_ value: String) -> Result {
		return value.rangeOfCharacter(from: NSCharacterSet.decimalDigits) != nil ?
			.ok(value) :
			.error(PasswordStrengthValidationError.missingNumber)
	}
}

There really is nothing special going on here. However, what does the validation for the weak error type look like? Well, here it is:

class PasswordStrengthValidator: CompositeValidator {
	let validators: [Validator]

	init() {
		self.validators = [
			PasswordLengthValidator(),
			PasswordIncludesUppercaseValidator(),
			PasswordIncludesLowercaseValidator(),
			PasswordIncludesNumbersValidator()
		]
	}

	func validate(_ value: String) -> Result {
		let result = validate(value) as [Result]
		let errors = result.filter { if case .error(_) = $0 { return true }; return false }

		if errors.isEmpty { return .ok(value) }

		let reasons: [PasswordStrengthValidationError] = errors.map {
			if case let .error(reason) = $0 { return reason as! PasswordStrengthValidationError }
			fatalError("This code should never be reached. It is an error if it ever hits.")
		}

		return .error(PasswordValidationError.weak(reasoning: reasons))
	}
}

As you can see, it is necessary to change the default implementation of validate as we would like to do a custom conversion to box the potential list of failures reasons into a single weak value. If we modeled the error type as Scott had them, this step would be unnecessary.

Finally, we look at the all up composite validator for passwords:

class PasswordValidator: CompositeValidator {
	let validators: [Validator]

	init() {
		self.validators = [
			PasswordEmptyValidator(),
			PasswordStrengthValidator()
		]
	}
}

Again, we can simply use the default implementations for our two validate functions as there is no special logic we need here. The usage code is:

let passwordValidator = PasswordValidator()
validate(value: "", validator: passwordValidator)
validate(value: "psS$", validator: passwordValidator)
validate(value: "passw0rd", validator: passwordValidator)
validate(value: "paSSw0rd", validator: passwordValidator)

With the output of:

value: "" => error(PasswordValidationError.empty)
value: "psS$" => error(PasswordValidationError.weak([PasswordStrengthValidationError.length, PasswordStrengthValidationError.missingNumber]))
value: "passw0rd" => error(PasswordValidationError.weak([PasswordStrengthValidationError.missingUppercase]))
value: "paSSw0rd" => ok("paSSw0rd")

In the End

This is really just a refinement of Scott’s approach. I think he started off with the right thought process. The biggest critique I have about his approach is in the end when he needed to use functions to encapsulate the construction the various composite validators. Using functions as constructors can often times mean you simply don’t have the right type abstraction yet. I do believe that is the case here, which is why I introduced the CompositeValidator protocol.

Update: Here’s a link to the full playground source code: https://gist.github.com/owensd/6a99ca908d3c13c8b19c9a42aaf3cd9d.

Composite Validators – Refined

Returned

I’m sitting here typing on, what is no question, a very beautifully designed piece of hardware that I just paid $2799 (+ tax) for. But the question in my mind: is it really worth it?

The answer: I really wish it was, but for me, it’s simply not.

There are good things about it, but at the end of the day, and maybe it’s partially because of all of the gloom in the political climate as well that has me melancholy as well, but I just don’t see myself having a long-term future in the Apple ecosystem, if the current trend continues.

This is what I’m looking to upgrade at home in the near future as I’m moving out of our temporary rental into our new home:

  1. Workstation
  2. Wireless router setup
  3. Home entertainment center
  4. Home Picture Management
  5. Secondary gaming machine

A few of years ago, I was under the impression that we’d be getting some better Mac Pro options that weren’t just tailored to heavy graphic workstations.

A few of years ago, I was under the impression that we were on the brink of getting better HomeKit wireless networking.

A few of years ago, I was under the impression that Apple was going to be really stepping it up with TV.

A few of years ago, I thought Apple was finally on the course to make managing my digital picture and movie life better.

It’s now been a few years. As I sit here in the present, this is the only thing I see coming out of Apple: thinner and lighter. Sure, there is some interesting stuff in the periphery, like ARM-based Macs. But honestly, what else is there? I don’t know.

The latest “Mac” event, and I use that term extremely lightly, hinted at what I truly believe Apple thinks (or at least thought at the time, maybe they’ve started to revisit that notion), that this is the future of the Mac ecosystem:

The MacBook Pro hardware setup

A silly image of Mac’s connected to ugly crap – or, what Phil Schiller actually presented.

That’s just not Apple to me.

When I was picking up this MacBook Pro at the Apple Store, there was an old Apple Cinema Display.

mc007

I had forgotten just how beautifully clean those monitors were. It made me sad. What also made me sad as I looked around the store: the shear dominance of everything but Macs.

It seems clear that the future Apple wants is not the future that I want for it. That’s ok. But maybe that just means it’s time for me to move on too. If four of the five solutions above I need to satisfy in the near future simply cannot be an Apple product, it might finally make sense to go back to having my workstation not be one anymore too. After all, a Mac is really only needed for the code signing and App Store submission process these days anyway.

Returned

MacBook Pro: Radeon 455 vs. 460

I was in the Apple Store last week and they had the MacBook Pro in stock! However, at the price I was willing to spend, they only had the Radeon 455. Now, I have a model with the Radeon 460 on order, but thanks to @reidmain, I’m able to get some very basic comparisons of the two.To m

Basically the question I want to know, should I cancel my pre-order?

Here are the Unigine Valley benchmarks (the other difference is the 455 model as the 2.7 GHz Core i7 vs. the 460’s 2.9 GHz Core i7):

Model Score FPS Min FPS Max FPS
455 1393 33.3 19.4 54.6
460 1629 38.9 21.2 66.6

1920×1080, Windowed, Medium Settings, No AA

Model Score FPS Min FPS Max FPS
455 905 21.6 14.1 35.9
460 1087 26.0 16.2 45.4

1920×1080, Windowed, Ultra Settings, No AA

To put it lightly, I’m a little surprised that all I’m seeing is roughly a 5 FPS difference. For my needs, this is a clear choice: cancel my pre-order.

MacBook Pro: Radeon 455 vs. 460

More Touch Bar Thoughts

The more I use the Touch Bar (or rather, look at it wishing it actually did something useful), the more I’m thinking of all of the missed opportunities. Fortunately, these aren’t fundamental design limitations, but only limitations with what we have to today.

Here’s a list of what I actually want in the touch bar:

  1. Fully customized Touch Bar region with Control Strip (we only have the “extended control strip option” today, and it’s missing functionality compared to the control strip present with the app controls enabled).
  2. APIs to add items into the control strip portion, like both iTunes and Xcode can do. I’m guessing that this will eventually come.
  3. Automator support to build up custom control strip items. This is a fantastic use case as it allows me to dictate what my quick and easy commands are. Though… with the announcement of the termination of both Sal and his position, I’m greatly concerned that Apple is becoming quite clueless here.

Those features above, those are “pro” features. Contextual app elements, especially those that are simply showing the same stuff in the app, like the “save” and “cancel” buttons (I mean really? I’d love to have been there for the conversation on how is such a great feature, are, in the nicest terms possible, a supremely weak use case.

I’m hopeful that things will get better. Maybe the control strip API support was just not ready yet (it is already a super buggy area. Once you have iTunes or Xcode open, you’ll get an empty icon in the control strip).

I guess I’ll continue my waiting for the “pro” Apple.

More Touch Bar Thoughts

The Touch Bar

This basically sums up my experience with the Touch Bar after using it for a day:

Overall, I think it is a huge usability nightmare.

Really, it’s pretty terrible. The screenshots make it look a lot better than it actually is. From a first take at the bar itself, it suffers from two really unfortunate limitations:

  1. No haptic feedback, there’s not even any auditory feedback that you’ve pressed or interacted with something.
  2. It’s blurry. It’s rendered right next to the super crisp and clean lines of the MacBook Pro, the keyboard key text, and the beautiful retina display – it really looks out of place.

This screenshot does not accurately represent the quality that is actually rendered.

safari-tabs

It actually looks nice and crisp there. But no… I don’t have a good enough lighting or camera setup to take a picture that accurately represents what the Touch Bar looks like in real life, but the best comparison I can think of is the difference between the non-retina and the retina iPhone displays. And you always have them side-by-side to look at things. I can feel my eyes re-focusing on them the bar and the screen as I look up and down from it.

Not only that, I’ve not found an app yet where I’m like, “oh, yeah, that’s really convenient that you’ve rendered stuff down in the touch bar.” You can see the screenshot above with the tabs… maybe that’s cool to you, but it takes significantly more effort for me to find the correct tab and navigate to it using the touch bar than to simply click or cycle through the tabs in Safari.

If anything, having the touch bar really makes it so I want to actually just touch the MacBook Pro’s screen. This is especially true during the configuration of the bar.

Maybe I’ll grow to like it over the next week or so, but my initial reaction is: wow, this thing is pretty crappy.

Thankfully there are options to hide the contextual app controls – they can be brought back up with a press of the “fn” key. I’ve customized my bar to leave it like this:

touchbar-my-setup

Maybe I’ll press “fn” every once in a while to see what apps have to offer, but most likely not. At least in this mode I don’t have to deal with the constant peripheral flickering I see as I navigate between apps.

The only thing I’ve liked about it the Touch Bar so far is the Touch ID integration. That’s been nice. However, if there was a proper 15” model with function keys, I’d return this model tomorrow morning.


Update Thursday, Nov 17th.

One thing I’ll add here: I think the biggest miss with the Touch Bar is that contextual UI in the bar is just not good. However, the power, that I think is really poorly executed, is the ability to control apps that are not the front-most apps.

You can do that today, but it appears that the only way to do it is to have the contextual UI available as well. Otherwise, you lose access that functionality. See below with the iTunes item within the Control strip and then that item expanded.

touch-bar-app-control-striptouch-bar-itunes-expanded-strip

What I want, is to have the ability to have those attachments in the control strip attached to the Siri button, like in the default Touch Bar setup.

But alas, I see no option here to help with me that:

screen-shot-2016-11-17-at-1-34-01-pm

That functionality would make the Touch Bar significantly more useful. Contextual use within the currently opened app… still not feeling it.

The Touch Bar

Electoral College

I keep seeing this float around:

I think this is a terrible idea. At the very core of our country, we are a federalist nation. That is, we are supposed to have strong state governments that are stitched together by a single governing body. Now, we can argue that we’ve continued to let this principle erode over our country’s lifespan, but I would argue that today we are seeing just how costly of a mistake that could become.

The point of the Electoral College is summed up here (we should not overlook that slavery also played a role too2):

https://twitter.com/AndrewCrow/status/797361644682833920

To reject the Electoral College is to reject the very founding principles of the Constitution. The Electoral College serves a similar purpose as jury nullification: it provides the people the ability to fix the outcome when something is not right. Here are some examples of it working: http://niagarafallsreporter.com/Stories/2013/Jul9/Examples.html.

Also, people talk about the voting power of the states. This comes from the balance of not having small states overwhelmed by larger states as each state gets the number of representatives plus the number of senators. So smaller states will obviously have their senate weight count more. Here’s a look at what that might look like with out election:

img_0002

Source: My Normalized Electoral College Sheet 

In other words: Clinton still loses. It also shows that California, Florida, New York, and Texas are the only states that would gain four or more Electoral College votes. So maybe it’s simply time to readjust the allocation again.

Now, people say that Clinton will win the popular vote by a “huge margin”1. I guess I just don’t find 1.5% of the population warrant the usage of “huge margin”. Also, I simply don’t buy the assumption that Clinton would still come out on top of the popular vote if those were the rules going into the election. It’s easy to say if we changed the rules now, she’d win, but that completely negates the strategy of the GOP this entire election. They knew they did not need the popular vote to win, so why go after it?

Until December 19th, there is still a potential recourse. There are many dangers with Trump that are outside of the typical Democrat vs. Republican policy arguments. I won’t get into those now. However, if you actually try to repeal the Electoral College, you remove the States last recourse at stopping an election outcome like this.

Here’s hoping they do.

  1. New York Times, Clinton’s Substantial Popular-Vote Win: http://www.nytimes.com/2016/11/11/opinion/clintons-substantial-popular-vote-win.html?_r=0
  2. Times, The Troubling Reason the Electoral College Exists: http://time.com/4558510/electoral-college-history-slavery/
Electoral College

A Christian in America – A Personal Story

I saw this stat that said that 85% of Evangelical Christians voted for Trump… I don’t get it… I mean, I do in a way, but it breaks my heart that they cling to a name they so clearly do not espouse the virtues of.

I’m a Christian. I believe in the Bible. I believe many things from the Bible that you’d probably call me a fool for. That’s fine. You can think of me what you want.

But here’s the thing, you can basically summarize the entirety of the Bible down to this, the only new commandment Jesus gave his disciples:

34A new commandment I give to you, that you love one another: just as I have loved you, you also are to love one another. 35By this all people will know that you are my disciples, if you have love for one another.

John 13:34-35 (ESV)

Now, that means more than I think many people realize as it’s not a romantic, wishy-washy type of love that we are so accustomed to in our culture. It’s not even a brotherly or camaraderie type of love. This is ἀγάπην (agápe) love: the unconditional love for another (especially in the context of God’s love for us). Thomas Aquinas defined it as, “to will the good of another”.

There are few modern day examples of this love demonstrated better than by the life of Dr. Martin Luther King Jr. He dedicated, and ultimately had taken, his life to see this realized throughout our country. To change the mentality of a nation so that it wouldn’t look at one another with disdain, but that we could see each other as a person with thoughts and ideas and wouldn’t be judged by the color of our skin.

And this, this is why I’m so heartbroken at those that call themselves Christian and voted for Trump. Today, the nation voted for someone that is the antithesis of everything that is at the heart of Christianity and at the heart of all the good things from the Civil Right’s movement.

When you voted for Trump, you voted to enable and empower this, whether you wanted to or not:

 

muslim attacks.PNG

Source: http://www.nytimes.com/2016/11/11/us/police-investigate-attacks-on-muslim-students-at-universities.html

Were there racist people before Trump? Of course. Did they act out? Of course. Were non-whites disenfranchised and belittled by even our government? Of course. However, Trump has finally given that hate a legitimate platform that they have been lacking for many decades. Even if Trump himself doesn’t want it to happen, maybe he’s more indifferent to it all, it’s unleashed now.

I do pray that our last line of defense in our government, the Electoral College, stands up for what America should be, and does not hand the presidency over to Donald Trump.

Either way, we are at the brink of a social revolution. How far, how quickly, and how extreme will it be? I don’t know, but I do know that we’ve finally arrived at the precipice.

A Christian in America – A Personal Story