Computers, Open-source, Ruby, Software, Thoughts, Web

new Job().beginTraining()

It has been an exciting month for me. I put in my notice with Influence Health at the beginning of June, and served through the end of the month. After that took 2 weeks off before my training begins for Doximity on July 16th. The training is in San Francisco, and then immediately followed up with a July 30th co-location in Boulder, Colorado. This position is remote, aside from the several co-locations done each year. I am excited to start with a new team, on a new project, with a mix of old and new technologies.

Over the career at Influence Health I don’t feel that I got much deeper in my knowledge of Rails. What I feel I gained instead was the breadth of general programming skills. I configured Github repos, setup Jenkins, scripted a Hubot instance to assign pull requests, and made a continuous integration system. I created new policies following best practices to open a pull request with a change, write unit tests, and have one other person on the team review your changes before merging. I implemented linting, and worked with one of my coworkers to bring Webpack into Rails to rethinking how we manage Javascript. I also went very deep into the AWS services touching S3, Lambda, RDS, Redshift, Data Pipelines, Batch, Step, ELB, EC2, ECS, Cloudfront, and into other technologies like PostgreSQL, Docker, ElasticSearch, Capistrano, EventMachine, and Daemons. Being exposed to all of these new services has made me consider different approaches to traditional problems, and I feel has made me a better developer.

The new job at Doximity sheds my managerial role that I was voluntold to do at Influence Health. I thought I might have enjoyed it (maybe I would have under better circumstances). At the end of the day it wasn’t being a manager that killed the deal for me. It was being a manager, while still being a tech lead, while being an architect, a core contributor, and many other things. To manage well is a full time job. Tacking it onto an existing role made me feel inadequate as a manager, and I don’t like that feeling. So with the managerial role off my title the new role is back to software developer, and I’m ok with that. The compensation is right, and I felt like I was getting further away from the code than I wanted to be. At the end of the day developing something and seeing it work is what drives me. There is a technical lead track that I might pursue in several months if I feel like I am ready.

The technology stack is a mixture of Ruby and Javascript. After working with Javascript more heavily the last 6 months I have mixed feelings. I’m definitely excited because I do think the future of web development has coalesced on Javascript. And Javascript has risen to the challenge and gotten a lot better. Gone are the imposter “rich internet applications” like Silverlight, and Flex. Gone are the browser plugins for languages like Java and Flash. Javascript just works. And the browsers are really blazing trails, even Microsoft, so I believe that learning Javascript is a solid career investment. There is an excitement in the ecosystem (a little too excited imo, but I’ll take that over being dead)

Popularity aside, Javascript has less magic than Ruby which is a again, both good and bad. I appreciate seeing require statements, and knowing with absolute certainty that private methods are private. In Ruby for everything you can do to protect something, someone else can (and I find frequently does) find a way to circumvent it. I especially appreciate the strong linting culture that mitigates entire debates on code style.

I find the syntax of Javascript to be unattractive coming from Ruby, but it is more consistent. All of the parenthesis, semicolons, etc are just noisy. The surface area of Javascript is also much smaller which leads everyone to jump to utility libraries like Lodash, Underscore, etc. The language just needs to keep maturing and building in common methods. Date manipulation in particular is atrocious. async/await seems like we finally have a clean syntax for managing asynchronous code.

I do still feel like we are fitting a square peg into a round hole by having client side, single page applications. This isn’t the way the web was designed (it was made for request/response), and the fat client pattern still feels immature. Having a client side framework like Angular, (or even a library like React) does take care of managing some of the complexities . GraphQL takes the sting out of fetching all the combinations of data you might want from the server. Auth is taken care of with JWT and services like Auth0.

On the server side, using Node has been a mixed bag. I would like to see a few big frameworks that the community standardizes on, however the mentality seems to be build your own framework from a collection of your favorite libraries. As a result you can’t just jump into a project and immediately know where things are. I do however really enjoy asynchronous execution of code. It is a little harder to write and understand but wow can it be fast. I have already seen very positive results from Ruby implementations of batch jobs that took hours converted to Javascript and taking minutes. You simply don’t wait around, and it can think of your dependency tree in a completely new way.

At the end of the day I am excited but a little cautious. Ruby + Javascript sounds like a killer combination if you use each tool for what it does best. I don’t see the Ruby community lasting another decade so this is the perfect transition point to jump into Javascript. And I’m glad that it was Javascript that won out over Flex, Silverlight, JSP, etc. At least for the next 5 years until the new shiny technology comes out and people jump ship.

Advertisements
quotes, Thoughts, Uncategorized

Fahrenheit 451

Everyone must leave something behind when he dies, my grandfather said. A child or a book or a painting or a house or a wall built or a pair of shoes made. Or a garden planted. Something your hand touched some way so your soul has somewhere to go when you die, and when people look at that tree or that flower you planted, you’re there. It doesn’t matter what you do, he said, so long as you change something from the way it was before you touched it into something that’s like you after you take your hands away.

  • Ray Bradbury
Personal, Thoughts

Pulling Away

I have felt a particular way for a long time. It has been a nebulous, vague feeling for most of it, but recently its started to coalesce in my head. Its a realization that I am pulling away.

I think it started with our second daughter, Adeline. Raising two kids is without a doubt, one of the hardest things I’ve ever done. Its incredibly rewarding, but it has taken its toll on my physically, emotionally, and mentally. At the hospital when Adeline was born my mom said to me that raising two kids is four times as hard. Extrapolating, I expect three kids is eight times as hard. That is how kids work I suppose. The chaos magnifies. I simply don’t think that I could have a third, despite strong wants some days.

I’m now 32, and the world makes less and less sense to me. Trends don’t interest me. I look at communities like Instagram, and Snapchat and I just don’t get it. Facebook has changed from my college days. What was a way to write to your friends is now a trash media outlet and everyone on it is angry. Maybe I boxed myself into some political bubble in their news feed algorithm. I’ve stopped visiting them, along with Twitter, Untapped, Yelp, Strava, and more. Its all needless.

I don’t really get the new movie trends, like the hundreds of superhero comic to movie adaptations. The first few were neat, but we keep remaking them.  I don’t follow sports. I have a hard time listening to new music on the radio. New fashions like vaping and skinny jeans just irritate me. Video games have gone to shit now that publishers are wrapped up in multiplayer and add-ons. Programming just feels like an endless reinvention of the wheel with diminishing progress.

Maybe it’s just what getting older feels like. Maybe it’s wisdom. Not falling prey to the fear of missing out. Focusing on what matters to me as an individual. Quit making everything a competition. Quit trying to impress others with checkins, and pictures showing how much fun you are having. Quit seeking peer approval.

Then last night the presidential election happened. It hit me in a way I didn’t expect. I educated myself on the issues, while staying away from mainstream media, talk shows, and largely out of debates with peers. I figured most of the drama was just for viewership by the media outlets. I believed that some people felt differently from me, but more were like me than not like me. But when the polling results came in, I found myself angry, confused, fighting back tears. It meant more than past elections. I’ve voted for losing candidates, and went on with life. This one stung. To me it was a signal of the end of what I understood our country to be.

I’ve been in this mindset for months now, and the election pushed me to write about it. I needed to get the way I’m feeling out of my head and down on paper. Is this just aging? Is this stress? Diet and exercise? Is this objectively where we are as a civilization, and everyone is waiting for it to change just like me? Have I just become bored, or complacent with my life?

I certainly feel old, tired, slow. Unnaturally. And I’m not sure what to do about it other than writing a cathartic blog post.

Open-source, Ruby, Software, Thoughts, Uncategorized

Implementing a Configuration

Have you ever seen a configuration in Ruby that yields to a block where properties are set on the yielded object? Rails does this with its environments files:

Your::Application.configure do
  config.cache_classes                     = true
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true
  ...
end

Devise is another great example of this pattern:

Devise.setup do |config|
  config.secret_key = '38c8e4958385982971f'
  config.mailer_sender = "noreply@email.com"
  config.mailer = "AuthenticationMailer"
  ...
end

This is an established way to pass in configuration options in the Ruby world. How does this work? What are the alternatives?

Under the Hood

Lets start with our own implementation from scratch. We know that we are calling a method (Application.configure, or Devise.setup) and that method yields to a block:

module Example
  class << self
    def configure
      yield Config
    end
  end
end

You can see that this will yield the class Config when we call Example.configure and pass in block. Config will need to define our properties:

module Example
  class Config
    class << self
      attr_accessor :api_url, :consumer_key, :consumer_secret
    end
  end
end

We can now call our configure method and pass in a block:

Example.configure do |config|
  config.api_url = "http://api.com/v1/"
end

If we try to set a property that does not exist in our Example::Config class, then we get a helpful NoMethodError:

Example.configure do |config|
  config.not_a_real_config_setting = "http://api.com/v1/"
end

# => NoMethodError: undefined method `not_a_real_config_setting=' for Example::Config:Class

This helps to define your configuration interface. Options are explicitly declared. They cannot be mistyped, or dynamically added without an explicit runtime error.

In practice, The definitions of Example, and Example::Class would live in a gem. The Example.configure invokation would live within the code that wants to configure the properties of that gem with things such as credentials, URLs, etc. This seperation of concerns makes sense. Gems should not know anything about the business logic of your application. It should be instantiated with configuration options passed in from the project. However the project should only be aware of the public interface of the gem. We are agreeing upon where these pieces of information are moving from one domain to another. The project doesn’t know where this information will be used, and the gem doesn’t know what the information is until we pass it. So far so good!

Using this Configuration

Now that we’ve passed our information inside the configuration block, we can reference these class level (static) properties in our gem:

module Example
  class Request
    def self.get(path)
      request = Net::HTTP.get(URI.parse(ExampleConfig.api_url + path))
      request['Authorization'] = auth_header(:get, ExampleConfig.api_url)
    end

    private

    def self.auth_header(request_type, uri)
      SimpleOAuth::Header.new(request_type, uri.to_s, {},
                              {consumer_key: Config.consumer_key,
                              consumer_secret: Config.consumer_secret}).to_s
    end
  end
end

This will do a simple GET request passing in SimpleOAuth headers. Inside the get method we call Config.api_url to know where the API lives. This was set by us earlier using the Config object. SimpleOAuth headers are supplied by again calling the Config. You would invoke it like so:

Example.configure do |config|
  config.api_url = "http://api.com/v1/"
  consumer_key = "1895-1192-1234"
  consumer_secret = '76asdfh3heasd8f6akj3hea0a9s76df'
end

Example::Request.get('/products') # => {products: [product1, product2, etc]...}"
Example::Request.get('/users') # => "{users: [user1, user2, etc]...}"

Example::Config becomes the holding location for your configuration information. And by making the properties static, you don’t have to worry about passing around a reference to the instance.

Alternatives

If the yielding to a block is a little too clever for you, you can always instantiate a class and pass in the configuration as part of the constructor:

class Example
  class << self
    attr_accessor :api_url, :consumer_key, :consumer_secret

    def config(api_url:, consumer_key:, consumer_secret:)
      self.api_url = api_url
      self.consumer_key = consumer_key
      self.consumer_secret = consumer_secret
    end
  end
end

This can be instantiated like so:

Example.config(
  api_url: "http://api.com/v1/"
  consumer_key: "1895-1192-1234"
  consumer_secret: '76asdfh3heasd8f6akj3hea0a9s76df'
)

Example.api_url # => "http://api.com/v1/"

This feels less encapsulated to me. Instead of having an interface for our configuration settings, we are just settings properties directly onto a class.

What are your thoughts? What advantages does the block style configure offer over the alternative above?

For more information on the Ruby gem configuration pattern see this excellent blog post:

Computers, Open-source, Software, Thoughts

AngularJS File Uploads with HTML5 FileAPI

AngularJS has an interesting gap in functionality that can make working with file uploads difficult. You might expect attaching a file to an <input type=”file”> to trigger the ng-change event, however this does not happen. There are a number of Stackoverflow questions on the subject, with a popular answer being to use a native onclick attribute and call into Angular’s internals (e.g. onchange=”angular.element(this).scope().fileNameChaged()”)

This solution feels brittle, and relies on some unsupported Angular interactions from the template. To work around this issue, Github user danialfarid has provided the awesome angular-file-upload library to simplify this process by extending Angular’s attributes to include ng-file-select. This is a cleaner implementation. This library also includes an injectable $upload object and its documentation shows how this abstracts the file upload process in the controller. This abstraction (if used) sends the uploaded file to the server immediately, and without the contents of the rest of the form. I wanted to submit this file change with the traditional all-at-once approach that HTML forms take. This way, the user can abandon form changes by neglecting to press the submit button, and keep the original file attachment unmodified.

In order to achieve this, I’ve created a solution that uses the HTML5 FileAPI to base64 encode the contents of the file, and attach it to the form. Instead of reinventing the ng-file-select event, I opted to use the angular-file-upload library described above. However instead of using the injected $upload functionality referenced in its README, we will serialize the attachment with a base64 encoded string.

To begin, create an AngularJS module for your application, and include the angularFileUpload dependency:

window.MyApp = angular.module('MyApp',
  [
    'angularFileUpload'
  ]
)

Next, we will create our AngularJS template and include our HTML input tags:

<div ng-controller="MyCtrl">
  <form ng-submit="save()">
    <input type="file" ng-file-select="onFileSelect($files)" />
    <input type="submit" />
  </form>
</div>

Now we can create our AngularJS controller, and define the onFileSelect function referenced in the the ng-file-select attribute:

class exports.MyCtrl
  @$inject: ['$scope', '$http']

  constructor: (@scope, @$http) ->
    @scope.onFileSelect = @onFileSelect

  onFileSelect: ($files) =>
    angular.forEach $files, (file) =>
      reader = new FileReader()
      reader.onload = (e) =>
        @scope.attachment = e.target.result
      reader.readAsDataURL file

  save: =>
    @$http(
      method: 'POST',
      url: "/path/to/handler",
      data:
        $.param(
          attachment: @scope.attachment
        )
      headers:
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        'Accept': 'text/javascript'
    )

Our controller is now in place. When the input’s attachment changes, onFileSelect is called which iterates through the collection of files (if multiple) and creates a FileReader instance for each one. The reader then has functionality attached to its onload event in the way of assigning the result to an attribute in our @scope object. The call to readAsDataURL starts reading the file and creates a data: URL representing the file’s data as a base64 encoded string.

Once the form is submitted, the save function is called from the value of ng-submit on our form tag. This performs a standard AngularJS XHR action, and includes the attachment assignment in the params. I have adjusted the Content-Type in the headers to communicate to the server that the content contains URL encoded data. If we had other form fields, we could serialize and append them to the params collection to send to the server alongside the attachment in the same place in the code.

Image Attachments

For added feedback to the user on image attachments, the img tag’s src attribute can accept a base64 encoded string as a value. Since we have this value from our FileReader object, we can update the view instantly with the file without doing any server side processing. To achieve this, we can add an image tag to our HTML file:

<div ng-controller="MyCtrl">
  <form ng-submit="save()">
    <img ng-src="{{attachment}}" />
    <input type="file" ng-file-select="onFileSelect($files)" />
    <input type="submit" />
  </form>
</div>

Next, we can make a few modifications to our onFileSelect function:

onFileSelect: ($files) =>
  angular.forEach $files, (file) =>
    if file.type in ["image/jpeg", "image/png", "image/gif"]
      reader = new FileReader()
      reader.onload = (e) =>
        @scope.$apply () =>
          @scope.attachment = e.target.result
      @scope.reader.readAsDataURL file

AngularJS two way data binding takes care of the messy details for us. The template is bound to @scope.attachment_url. We do some safety checks that the filetype is an image, and then we assign the attachment_url key to the base64 encoded image. A call to scope.apply() will repaint the screen, and the user will see the image they have attached displayed.

Thanks to Nick Karpenske, and Robert Lasch for help with the implementation!

Computers, Personal, Software, Thoughts

“The Deadline”: Part 3 on a Series on Leadership in Technology

Quite a bit has changed since my last post on leadership. I’ve been promoted to the capacity of full time team lead after my mentor, and manager left to work for another company. I was learning a great deal everyday, and being turned loose to manage the team on my own has been a baptism by fire. I’ve applied what I’ve learned already from my previous mentorships, and I’ve learned a great deal more over the last few weeks.

High bandwidth communication is key

I would have never gotten through the last few weeks on emails, and instant messenger alone. Its very important to have communications by voice to keep everyone updated and on the same page while respecting each other’s time. Several times in the past week I’ve watched an email thread bounce back and forth between many participants, only to get boiled down into a concise message at a standup meeting. A five minute verbal QA would take hours via email. Especially across different timezones.

Delegate, delegate, delegate

When moving into a managerial capacity, the content of your day to day work shifts dramatically. The first few days without being in the code left me anxious. But you know what? We have good guys that understand even more than I do, and if you give them a problem, they come back with a solution. Its hard to trust that it will happen, but it did. Over and over again. The key is not in just throwing out a problem and coming back the next day to find a solution. You should be available for questions, and clarification continuously throughout the development of the solution. I often found that checking in a few times a day on each developer was sufficient to answer any questions, understand the progress, and get a rough idea of when something would be delivered. A few times they would casually mention that they are stuck trying to figure out ‘x’. Turns out I know about ‘x’ and after a brief chat with some pointing to places in the codebase they got it squared away.

Be crystal clear about your requirements

We had a new screen we wanted to develop. We had a mockup done by our front end guys. Our BA loved it. Everyone was on the same page. Until we began to implement it and all of these tiny edge cases popped up. I’d assume a course of action was the correct one to take, only to discover that our stories were getting rejected by QA. Turns out we don’t share the same brain, and what I call working, someone else will call a defect. That creates a lot of extra work to resolve what is now a defect. Closer to the deadline of the deliverable, when I switched over to voice communication instead of IM, I was able to lock in requirements quickly and get instant feedback on how we should handle certain edge cases. Don’t be afraid to bother the higher ups with technical questions, because it is up to them to provide the definitive answer. You aren’t doing yourself any favors by shielding them from it and substituting their would be solution with something you invented.

Front load work you are less certain of

If you aren’t clear of how something is going to be executed, that is a problem. Its your job as a manager to find out! You don’t need to know every technical detail, but you do need a clear understanding of who the key players are, what the testing process is like, and how you will get this feature through QA and accepted by the business. We had some work on a feature that impacted a few systems downstream. Did we put this off until we took care of the easy stuff? Nope – we started with the pain in the butt feature. And good thing too because we were working on it up until the last minute. We didn’t realize how much latency there would be in getting just a ‘its working’, or ‘its not working’ from all the parties downstream from us. If you aren’t sure, begin immediately to error on the side of caution. The easy work you have a clear understanding of, and it should take a backseat to anything that isn’t as clear.

Pad your estimates

This entire iteration I was too optimistic with what we could turn out in a day. Estimating is hard, and I’m convinced we all suck at it. I’d like to believe my guys can come up to speed on a new technology stack and crank out some impressive code but there is a learning curve. Sometimes the only way forward is a painfully slow dive into the documentation. There are test suites that take forever to run. There are rejections when it comes time to merge, meaning the suite has to be run again. There are the seemingly simple issues that once you dive into become much more complex than anticipated. Rarely did we close a feature or bug in the amount of time I assumed it would take. Because of this I’m going to start padding my estimates to compensate for all of these little details that add up to something bigger.

And finally – know when to ask for help!

There was a certain point in the sprint when I knew we weren’t in good shape to hit our deadline. I mulled it over in my head and stressed about it, and let my pride get in the way a bit and was convinced that asking for help wouldn’t be necessary. It was a mentality of “if I can just get through these few stories here we will be back on top”. But of course, I’m sucked into a meeting, or new bugs pop up, or the feature I’m working on before it runs way over on time. Don’t hesitate to ask for help when you first identify the need for it. Forget how bad you think it will look. Forget the anxiety of revealing rough new code to outsiders. Its worse if you don’t ask and end up missing your target. I was surprised at how strong the support was once we asked for help. I had 10 extra people jump in and had them all working in parallel on the feature. My entire day was pointing people to new work, and answering questions, and following up on when it would be merged. And the astounding thing was by NOT touching the code, we were delivering more than if I had put on headphones and jumped in myself. And for the record, there was a minimum of sniping at our technical solutions from outsiders. It felt good to know we were a team and it didn’t need to be a perfect solution before you left outside people in for help.