Site Changes Coming

This site has been around in its current form for many many many years. While I have updated the theme and the fonts, this site has been a WordPress site for as long as I can remember. My oldest post was from 2007 so that is about 15 years.

Times are a changing and I find myself with some downtime between jobs. I’ve decided it’s time to take a little more control over the experience. So that leaves some options. Really learn modern day PHP and customize the crap out of my WordPress experience, or consider something else. I have built a lot of sites with a lot of different technologies aside from this main site, but WordPress has always been pretty easy for me.

There are many options out there, but honestly, I think the static site generators are the way I’m leaning. I don’t really get a lot of useful comments on these posts, and I spend most of my time just removing spam comments. Static sites are super fast to generate and quick to deploy. I can still look at solutions for interaction.

Because I’ve started learning Go recently, I’m thinking about redoing the site in Hugo. I will try to maintain as much content as I can from the past and bring in some new stuff. Just a warning, some changes may be coming.

Documentation Formats

Life is full of things to catalog, especially for someone like me. Someone who loves organization in data and looking for patterns. Someone who is convinced that the random things in my life will probably come together someday like the unification theory. But how? How does one sort, contain, and search data?

The first step is recording the data. There are many ways to do this. Databases have traditionally been a great way. NoSQL databases with their loose document format are interesting. The second brain methodology uses documents or notes to contain the same thing. And while these documents can be formatted in things like Markdown and have front matter for categorization, much of the data is contained in the raw text which means a human has to parse and read it.

Before you expect this post to come to some epic realization, tl;dr; I still don’t have one. This post is about the methods out there I’m considering for sorting my life.

Option 1: SQL

I’m not a fan of no SQL databases. From my point of view, if you are going to create data to exist in a place that is typed, loose document formats make comparing and reading things hard. So structured data is better, hence SQL.

Pros:

  • The data is structured from the start
  • There are many different options for which SQL platform to use and many of them are interchangeable so there are options.
  • Things like normalization define best practices for working with something like this, so you don’t have to develop them yourself.

Cons:

  • You need to run a server somewhere.
  • It is not easily human decodable.
  • You need to learn to use SQL to really be successful and joins are fun (and hard).
  • Because structure is required you have to define it up front.

Option 2: Markdown

This is honestly what I’m currently using in my second brain with Obsidian. This may be the best of all worlds. It has the notion of storing structured data in front matter, and throughout the document with special tags. Much of the document remains readable in sentences, but it is in loose format and you have to create and maintain your own formatting standards.

Pros:

  • Format is loose so you don’t need to stress about it.
  • Much of the notes are human-readable.
  • There are many tools to convert markdown to the web for sharing.
  • Cost of starting is very low.

Cons:

  • Because the format is loose, the responsibility lies on the creator to maintain the structure desired.
  • The organization of individual documents is also important.
  • Search is only as good as you are at searching and remembering.
  • It’s easy to end up with a mess of documents.

Option 3: Stricter document format

This category contains things similar to markdown but with more structure. This category fits things like JSON, YAML, and TOML. This is following the Pragramtic Programmer guideline of storing things in the text but putting some structure behind it. Some of these formats are more readable than others.

Pros:

  • Easily computer parsable.
  • More human-readable than a SQL database

Cons:

  • No official typing.
  • Need to use a validator to confirm you have a valid document.
  • Nothing requires the structure like a SQL Table so searching could be difficult.

Summation

I don’t have a conclusion. I’m still thinking, but these are interesting options of how to start really putting the data together. Our lives are full of data, it’s a shame when it gets lost or mislabeled or put in a place where we can’t find it. Hopefully, I’ll start putting together something more useful.

Dabbling in Swift

Free MacBook on wooden floor

For many years of my life I was an iOS Programmer. I worked in Objective-C, but Swift came out while I was working transitioning out of that area. Swift has always been a bit confusing for me, but I have a new complaint today. The amount of changes in Swift has caused a lot of online code to be out of date, and hard to parse.

The problem. I’m looking at my address book and I want to iterate through my contacts. I started by looking at ABAddressBook, but it turns out that technology has been depricated. Then I started looking at CNContactStore which is the new hotness. There are several fun methods on that object including unifiedMeContactWithKeys which is pretty cool. It only returns my contact, not all contacts, but at least I was able to get it work. There is a similar function called

func unifiedContacts(matching predicate: NSPredicate, keysToFetch keys: [CNKeyDescriptor]) throws -> [CNContact]

You try to pass in the truthy predicate and it rejects it. You need to actually use the

enumerateContacts() method. Some examples mix strings and other types with keys and that causes problems. Just using a list of Keys worked. Here is the final code that worked:

//
//  main.swift
//  contactsexport
//
//  Created by Zachary Cohen on 12/23/22.
//

import Foundation
import AddressBook
import Contacts

print("Hello, welcome to the AddressBook Scraper")


var store = CNContactStore()

store.requestAccess(for: .contacts, completionHandler: { (access, accessError) -> Void in
    if access {
        print("access granted")
        print(access)
    }
    else {
        print("access denied")
    }
})


let nameKeys = [
    CNContactNamePrefixKey,
    CNContactGivenNameKey,
    CNContactMiddleNameKey,
    CNContactFamilyNameKey,
    CNContactNameSuffixKey,
    ] as [CNKeyDescriptor]

let allContactKeys = [
    CNContactNamePrefixKey,
    CNContactGivenNameKey,
    CNContactMiddleNameKey,
    CNContactFamilyNameKey,
    CNContactNameSuffixKey,
    CNContactOrganizationNameKey,
    CNContactDepartmentNameKey,
    CNContactJobTitleKey,
    CNContactBirthdayKey,
    CNContactNicknameKey,
    CNContactNoteKey,
    CNContactNonGregorianBirthdayKey,
    CNContactPreviousFamilyNameKey,
    CNContactPhoneticGivenNameKey,
    CNContactPhoneticMiddleNameKey,
    CNContactPhoneticFamilyNameKey,
    CNContactImageDataKey,
    CNContactThumbnailImageDataKey,
    CNContactImageDataAvailableKey,
    CNContactTypeKey,
    CNContactPhoneNumbersKey,
    CNContactEmailAddressesKey,
    CNContactPostalAddressesKey,
    CNContactDatesKey,
    CNContactUrlAddressesKey,
    CNContactRelationsKey,
    CNContactSocialProfilesKey,
    CNContactInstantMessageAddressesKey,
    ] as [CNKeyDescriptor]

do {
    let contactStore = CNContactStore()
    let me = try contactStore.unifiedMeContactWithKeys(toFetch: nameKeys)
} catch let error {
    print("Failed to retreive Me contact: \(error)")
}

do {
    let contactStore = CNContactStore()
    let fetchRequest = CNContactFetchRequest(keysToFetch: allContactKeys)
    try contactStore.enumerateContacts(with: fetchRequest) { con, response in
        print(con);
    }
} catch let error {
    print("Failed to retreive Me contact: \(error)")
}

I’m still working on the project and there is bunch more to do this, but this is a start and figured it was worth putting out there.

Building Apps In Airkit

I work for Airkit. I’m technically a Solutions Engineer but have done a bunch of building and education for the product as well. While the company has a bunch of documentation about how to use each tool, I figured I’d write quickly about how I build an Airkit App, what some of my practices are, and generally how I go about things.

Start with the UI

My first big tip is to start by creating the UI. One of the greatest things about Airkit is its ability to rapidly prototype interaction with your end users. Create the app quickly and show it to users. Often there are use cases that are missed when initially thinking about a project and this rapid prototyping brings them out.

Variables and Types

Create types for your complex object. If the data is going to be stored in AirData, then I create an AirData object, but Custom Types are good to explain what you expect the data to look like. Knowing the format of your data is helpful when using it to fill in form details data ops.

Naming is also important. Tables are capitalized where as instance variables are lower snake case. Profile constants can be capitalized snake case. Following this convention will make things clearer to read, but is not enforced by the platform. It is useful for understanding how variables are used across the app.

Scoping of variables is also important. In general, the goal is to minimize the scope of variables as low as possible to allow for more reuse of your components. That means if it is possible keep your variable on a web page then do, because it will come when you copy and paste the page. If you move it up to the flow level you will need to copy the entire flow together to have access to the variable. The downside of keeping everything at the page level is that you might end up passing it in to a bunch of pages, which is also not good. That is the trade off.

Also of note, because of some legacy notions, variable scopes are a little confusing:

Web Builder ConceptVariable ScopeNotes
JourneySessionThis is available anywhere in the runtime, but must be passed into data flows.
Web FlowActivity GroupAn activity group is available for all the web pages and actions on the flow.
Web PageActivityAvailable only in the context of the web page.

Variants and Themes

While each individual element has its style properties in the web builders inspector, the best practice is to store things on variants for each type. Even if the variant is only used once. This gives clear intention to the way you are styling each component and all styles can be managed directly through Theme Builder. It allows them to be reused as well.

Getting Help

There are plenty of ways to get help with Airkit. Start with the support site and if you can’t find the answer there you can always post a question on the community board. If that doesn’t work you can send an email to support@airkit.com.

HTML Email

What some of you may not know is that much of the time at Salesforce was spent in the world of electronic mail (or email for short). Email is interesting and relevant today because almost everyone has it and communicates with it. It is an official form of communication.

What you may not understand is that the world of email is rather confusing. Basically, the email that comes over the wire is presented to you by your email client and where email gets very confusing is that there are a million different email clients. You probably use more than one. If you look at your email on a mobile device and on a computer that is two different clients. Then when you think about 3rd party clients and even GMail which renders in a browser, you have a client which is actually a client within a browser.

Because of the various numbers of email clients and security concerns, while the web has advanced, email was still written and styled like the early 2000s web. This means table layouts, no real stylesheets, and things like the center tag from way back in the day.

When I left Salesforce, I was hoping that my email wondering days were behind me. Well, for the most part, they are, but one common thing our clients need is to send emails to their clients. Bringing me back to writing stylized email HTML like the 2000s in table layouts.

Despite being very forward-thinking when it was first created, Gmail is usually the hardest client to style for. It’s not really their fault. They are presenting your email in a web browser and they have to be secure on their side of things. I don’t begrudge them thinking about branding and security. Still, things are starting to change and Gmail is now supporting some new things:

Gmail isn’t the only client, though. Because of this, much of the email stuff is still being done with tables. This is pretty challenging for those of us who have spent a bunch of time learning to do things right in CSS (though, to be fair, I’m not the best at CSS).

The association for me feels a bit like the Cobal programmers who were needed to fix all the old code used before the year 2000. Granted, we have better tools for conversion, but this does feel a little archaic.

A Good resource is:

https://www.udemy.com/course/html-email/ – a good course on how to work through HTML email.

I’m learning more things as I go through this process. So far, I’ve learned that not all divs are respected and also that you have to use a capital M in margin for outlook. You also cannot use SVGs in email, you must use PNGs. More lessons to come as I dig through this project.

New Home

It’s taken me a fair amount of time to do this transition. I’ve been switching from LunarPages to DreamHost for a while now. LunarPages just stopped being up to date with all the technologies I needed in order to host all the projects I wanted, but I was (sort of still am) worried about moving from host to another. My primary email is associated with this domain (zacharyc.com). Also, I had a lot of secret hidden files and tools placed around the old website that I had been collecting pretty much since college (when I first started using lunar pages). Yes, that was over 13 years ago.

Lets define the type of technologist I am: I enjoy solving technical problems, but time is limited and there are too many problems for me to be an expert in all of them. I don’t want to be an email expert, but I do want email. I don’t want to be a server administrator but I do want my servers to be secure. So I pay other technologists to worry about those problems so I can worry about the ones I need to worry about. If I spent the time it would take to be an expert in those, I wouldn’t have the time to do all the other things that I want to do.

Looks like DreamHost is doing a pretty good job at meeting my needs. The move was stupid easy. When hosting a new domain on DreamHost, there is a checkbox for them to host Google Suite. All you have to do is check that box, and point the name servers to dream host and the magic works. I keep sending test emails to make sure they are still going through, but so far so good.

Also of note, I’m using a new theme here. I found it when I created a temp backup of my WordPress site on WordPress.com. The theme is called Independent Publisher 2. It’s not easily accessible from the themes download but it is public at GitHub: https://github.com/Automattic/themes/tree/master/independent-publisher-2 and it is working great on installation here. Had to do a couple of tweaks to get it where I wanted to be. I dropped the side bar on the main pages, and moved search to the footer. Other than that, pretty smooth.

TLog-007 Nitro Morning

This post was pulled from my TLog project, but it felt relevant enough to make it to this blog as well. Some interesting stuff about reading and writing code.


I’m trying the Nitro Cold Brew coffee from Stumptown that they just started carrying at Planet Granite. It is tasty, but I like the regular cold brew better and will be sticking to that in the future. Still, I do love coffee.

Grateful List

I was listening to a podcast the other day, I believe it was Finding Mastery with Ariana Kukors: Swim. And they were talking about gratitude practice. The part that really stuck with me was that practicing happiness is really hard. Being happy is a by-product of the world around and the best way to approach getting that feeling may be through practicing gratitude. I’m going to try and say three things I’m grateful for each day.

  1. I’m so grateful that we as humans discovered coffee. It has a profound effect on my life and while I only drink about 2 cups a day, I love it.
  2. I’m grateful that I can afford to take as many pictures as I do now. I love photography and there was point when I was in college when I felt like it was too expensive. Thankfully I can now afford great gear and enjoy using it.
  3. I’m very grateful for my climbing community. Yes, I don’t see as many of them as much as I used to, but I love having a second home at the climbing gym. It is more adult that my cheer community (not that I don’t appreciate that as well), and much closer to my house.

Reading Code

I spend a lot of my time reading objective-c code for work. Reading the basic syntax is pretty easy, but understanding what is going on in someone else’s code has always been relatively difficult for me. I’m not sure how everyone else does it, but the way I tend to read code is to go through a live example of the code and see how variables are manipulated. I like to track a path from a point I understand to a point I need to discover. The larger the piece of the code the harder it is for me discover the flow and the process.

The best analogy I have to this process outside of code is my attempt to read the Odyssey. I moved around a lot as kid and didn’t get to read greek theology in school. I have tried to pick up post school, but understanding the Odyssey or the Illiad has been very hard for me. I can read the words and understand the basics of what’s happening, but I’m not sure I can see the forest through the trees. When you are in class, you have a teacher and class to discuss the book with. The concepts in the book are discussed and you collectively discover what is going on.

When reading code, the teacher/class is akin to being able to talk to developer who originally wrote the code. Sometimes they are sitting right next to you. Sometimes they are downstairs or close by. Sometimes they are phone call or email away. Sometimes there are cliff notes in the form of a really good tutorial or ReadMe. Most of the time, though, you just have figure it out on your own. If the code is written using some common conventions (like a restful api, or common design pattern), it can be easier. Sometimes the code is all over the place and impossible to discover.

Yesterday I was working on understanding MGSwipeTableCell. It’s a pretty well built piece of code, but still rather confusing to figure out for me. I figured out what I needed to, but only after a couple hours of debugging. I wish I had done a better job reading the original piece of code from the beginning.

Writing a Safari Extension

I’ve switched to using Safari as my primary browser. It works pretty well because I use it on all my devices so passwords and bookmarks are available on all devices.

The one downside, the developer community isn’t as big. We use Github at work for all of our repositories. Github code diffs are constrained by the width of their center column. On larger diffs this can make it hard to see all of the code without tons of scrolling. There is a chrome extension for this task, but there hasn’t been a safari extension for this same task, so I decided to write one.

I have worked on several chrome extensions in the past, so I thought this would be pretty easy, but there are a couple of challenges that I didn’t expect in completing the code. I’d like to share my experience with anyone else starting to write an extension, so hopefully you don’t run through the same issues that I did.

Firstly, you can see the code I used to make the extension here.

This essentially takes something like this:
Narrow Github

and turns it into something like this:

Wide Github

Here are some of my tips for writing a Safari Extensions:

  • If things aren’t working the way you expect, don’t trust the reload. Restart the browser!
  • Even if you just want to do something simple, you need to have a base html page. This page can hit your javascript, but you need to follow the developer instructs.
  • Your HTML page can listen for events and then send actions to your javascript, but you have to listen to all commands and filter out the ones you don’t want.

While I’ve shared my extension with a coworker, I’m pretty sure I”m the only one who uses it. You an download the extension from here.

Comments and suggestions are welcome.

Custom UITableViewCell Layout

At work we were trying to create a custom UITableViewCell. We wanted something that looked like this:
tip cell

Here are some of the factors that made this problem more difficult:

  • Our one custom cell was in a UITableView of regular cells
  • The fonts for each of the items in the cell were pretty consistent with the rest of the table view
  • Like every other cell, we wanted to it to be indented based on cell.separatorInset

I looked at several ways to approach this. I tried using a custom table view. I tried subclassing a UITableViewCell. I finally landed on trying to override the tableView:willDisplayCell:forRowAtIndexPath: and it is worth explaining why.

First approach was getting a custom view in place. I turned this approach down because my view really wasn’t that custom. It was actually a tablevViewCell. It actually looked remarkably close to a standard table view cell. It had a text (in this case an NSAttributedLabel), and a detail text (the amount). Putting in a custom view would have required hard coding the layout to match the rest of the cells in the table and that seemed wrong. I also ran into a bit of confusion around getting my separator to be the correct size.

Then I tried subclassing the UITableViewCell. I know subclassing is frowned upon, but I only wanted to override layoutSubviews. I took the accessory view and tried and moved it to an offset of the tip label. I ran into a problem where the textLabel and detailTextLabel font color was being set to gray by the fact that I had userInteractionEnabled set to NO. If that sounds crazy, it should. Here’s a picture of what I saw:

cell

After overriding UILabel and trying to see who was calling setColor on it, I came up with nothing useful. This felt like the wrong approach.

Lastly, I looked at tableView:willDisplayCell:forRowAtIndexPath:. When you first get into this method, the cell’s subviews frames have yet to be calculated. I called [cell layoutSubviews]; which is costly, but get the dimensions I needed. Inserting the the editView after the label is then simple math. Here is what the code roughly looks like.

https://gist.github.com/zacharyc/8141791.js
gist

The downsides of this approach is the double rendering of the cell, but the benefit is that we get to keep our cell as close to factory as possible. In our case, we have one custom drawn cell on the page, so the performance doesn’t take that big of a hit.

There are other approaches to this problem, namely Mensa Smart Tables, but including another library seemed like overkill for what we needed.

Screening The Past

It’s been over a year since I left my roll at Motorola working with a team of very talented web developers on Montage. During my time with that group I worked on a side project for automated testing called “Screening”. I wrote a couple of posts (or at least one post) about chromedriver which we used to power screening. Still, one of the big personal accomplishments for me during that time was being published at Ars Technica. I was one of three authors on a post about the tools we were working on. The project has since been abandoned, but you can read about it here.