lemonbytes

husband, dad, steelers fan and software engineer


I’m a big fan of the Marvel Cinematic Universe. I don’t hesitate to get a baby sitter and see new releases in the theater and I’ve pretty much preordered every release (sans Guardians 2). I love the genre, but even more so I think the MCU represents some of the best movie writing of my lifetime. Consistently the MCU rolls out great content, so that even the worst MCU movie is still a great movie. Not even Star Wars can rival the consistent greatness of the MCU’s story telling.

Because I’m such an MCU nerd I often get asked to rank the movies from my favorite to least. That’s no easy task! I’ve tried this before with Star Trek and Star Wars where the disparity between a great movie and the bottom of the barrel is stark. In the MCU that disparity is narrow and sometimes hard to navigate. The middle of the list of also especially difficult to decide because they’re on such even ground with each other. Nonetheless for you, dear reader, I shall endeavor to order these movies. Please note, this list is fluid and I have no reservations about updating this list over time.

Lastly… don’t ever watch these movies in this order! The MCU should always be watched chronologically, period. Unlike Star Wars the release order matters, with but a few exceptions that, quite honestly, are not worth taking out of release order (looking at you Captain America: First Avenger and Captain Marvel).

  1. Avengers: Infinity Wars
  2. Avengers: Endgame
  3. Captain America: Civil War
  4. Iron Man 1
  5. Thor: Ragnarok
  6. Spider-Man: Far From Home
  7. Guardians of the Galaxy
  8. Captain America: Winter Soldier
  9. Avengers
  10. Black Panther
  11. Captain America: The First Avenger
  12. Captain Marvel
  13. Ant-man
  14. Dr. Strange
  15. Spider-Man: Homecoming
  16. Iron Man 2
  17. Thor
  18. Age of Ultron
  19. Iron Man 3
  20. Thor: Dark World
  21. Guardians of the Galaxy 2
  22. Ant-man & the Wasp

A few words (possible spoilers below)…

  • Notice the italics? These are movies that I struggled to sort amongst themselves and I would not object to someone’s personal reorganization of 12-18.
  • Yes, Infinity wars tops Endgame. Why? Infinity Wars is arguably the best most complete story in the MCU. They weren’t afraid to leave you entirely hopeless and that made this an emotionally gripping movie. Endgame is great, especially the final scenes, but as a whole the film isn’t greater than the fantastic writing of Infinity Wars.
  • Why is Age of Ultron so low? Yes, we get Vision, Scarlett Witch and the fist mention of Wakanda, but while there’s some great stuff going on here it is all in all a weak movie with lots of holes. Bottom line is it could have been better. It’s critical to the development of the MCU’s story line but I never find myself going back and rewatching it because I want to.
  • Dark World: Elves, enough said.
  • Guardians 2 has one of the best opening 30 minutes in the MCU. It’s hilarious and just great entertainment. After that 30 minutes we slip into the “I’ve got daddy issues” phase of the movie and the writing just goes down the drain. I can also make an argument that this is the least valuable movie to the franchise. What does it add to the ultimate culmination of Infinity Wars? Nothing.
  • I wanted so badly to love Ant-man & the Wasp, especially since Ant-man has long been a favorite of mine. I was ecstatic that we got the Wasp and that she was so key to this film, but the problem here is the villain. Which one, you ask? Exactly! This movie struggled to identify a clear bad guy and suffered because of it. Yes, it was hilarious and yes the post credits scene is absolutely critical to Endgame, making it one of the most necessary movies to watch going into it, but all in all it was just bad writing. My biggest fear from this one is that they don’t make a third, because that would be a travesty.
  • There are a ton of Captain Marvel haters out there, but I am not one. The biggest criticism I’ve heard is about Brie Larson’s almost stoic performance. Those with this criticism simply don’t understand the character and clearly don’t understand the Kree. So if Brie Larson’s sometimes emotionless acting bugged you, go do yourself a favor and read up on the Kree. If there’s anything to fault this movie for it’s probably the lack of depth around Kree culture, but then again hey we didn’t need (or want) an Endgame-length movie here.
  • Why is Far From Home so high? Well, I just watched it! But more so than that it ended up being more of a comic book styled movie than other MCU flicks. It has great character development for Spider-Man too. I loved that it was intrinsically tied into Endgame without being fully dependent upon it. There are so many great nerd-nods in this movie that MCU lovers will gush over it. Lastly, it finally capitalized on BARF, this odd left field reference in the beginning of Civil War that had until now never been capitalized on. MCU fans have been patiently waiting for something to be made of BARF and now we’ve got it in Mysterio!
  • Many of my friends will recall that for a long time I strongly disliked the first Avengers movie. So it might seem odd that it now stands in the top 10. What changed? I have long loved the story telling and character development of the MCU far more than I did the special effects and elaborate battle scenes. This is why Captain America: The First Avenger sits so high on my list, when for many it is near the bottom. The first Avengers is an action movie that has an amazing amount of ground to cover and thus it spends a lot less time on character development than say Ultron. What changed my mind was actually Endgame. As I re-watched the entire MCU in preparation for Endgame I found myself coming back to that first Avengers movie and really appreciating how much is setup for the rest of the MCU in that movie. It’s this appreciation that drove it up so high on my list.
  • What about The Incredible Hulk? Well, what about it?

React PouchDB Components

by Stan Lemon


Last night I released a new library to GitHub and npm called React PouchDB components. I’m excited to share this library, which started as an experiment to illustrate to my friend Jon how easy it could be to leverage PouchDB in React. After enough tooling around I suspected that the pieces could be extracted and shared more broadly.

There are a number of different ways to deal with state in React, everything from the simple setState() to redux. Most sites need remote data, and so as a developer your options become a little more complex, leveraging promises inside of componentDidMount() or tools like redux-thunk. These are all great, but what I wanted was a simple way to fetch data into PouchDB and for it to be declarative.

Here’s what I imagined…

import { Database, Document } from "@stanlemon/react-pouchdb";

function App() {
  return (
    <Database>
      <Document name="my-document">
        <MyComponent />
      </Document>
    </Database>
  );
}

function MyComponent({ name, description }) {
  return (
    <div>
      <h1>{name}</h1>
      <p>{description}</p>
    </div>
  )
}

There are two components here, the first <MyComponent /> is a simple view, it renders some properties that are passed to it. The other is <App /> which declaratively establishes a PouchDB database connection using the <Database /> component. This component can take an optional name and remote URL for syncing. The <App /> component also uses the <Document /> component which is responsible for fetching data out of a PouchDB document and setting it as properties on <MyComponent />.

One of the other advantages of the <Document /> component is that it provides a property to it’s children called putDocument() that allows you to update the state of your document, just as you might when using setState(). This method eagerly updates the component’s properties, and then ensures that the document is updated in PouchDB.

As an added bonus, if you’re syncing your PouchDB database to a remote CouchDB instance, the <Document /> component will update properties when change events occur. This means that you can sync down remote updates with little effort in near real time.

There is a working example in the GitHub repository under the ./example/ directory. It has it’s own README and is really easy to spin up and start playing. You can check out the example app over on glitch. This example app showcases several different ways to leverage a document including <Document /> and a higher order function withDocument().

Ready to give it a spin?

npm install --save @stanlemon/react-pouchdb pouchdb

From there the README is your friend!

This library is intended to quickly get a PouchDB database into your react application. It won’t work for every situation and there are definitely more complicated use cases that it does not cover, but as a starting point it should get you off the ground quickly. It’s also worth noting that this library is not intended to work with other state container libraries. Maybe it does, but that’ll be purely by chance. If you are using something like redux you should consider taking a look at redux-pouchdb.

Please reach out with feedback! I love questions and suggestions so send them my way.

Stay tuned, I have some more PouchDB related goodies coming.



Author’s Note: I originally wrote this during the government shutdown earlier this year, but thankfully that’s now over and I can maintain my streak of not writing about politics.


Budgeting is an exercise in compromise. Compromise is the right way to view it because unless you are really wealthy you never quite have enough money to buy and consume everything you want. Or at least, if you’re like me you don’t. I’m sure somewhere out there is a perfectly content person who isn’t filthy rich and has everything they want - but that’s not me. I constantly find myself thinking things like: wouldn’t it be great to have a new iPad? Just because I want something though, does not mean I buy it. I have bills to pay, mouths to feed and other commitments that all force me to make a compromise, at least for this month.

Let’s take a look at an example of everyday compromise in budgeting: let’s buy a car with financing. Before you sit down to sign the paper to buy a car you have to pick one out. Often you pick one out off of a lot. Your choices are limited by what’s available at that particular dealership. You may decide to buy the blue car that doesn’t have the sun roof over the red one that does because you like blue better. That’s a compromise. When you do sit down to finance it you have choices: a 3, 5 or even an 8 year car loan. Each requires a different amount of money paid for a downpayment and each will require a different amount of money monthly. As you continue the cycle of evaluating your options you are making more compromises, trading one thing for another in the hopes of reaching the ultimate goal: driving away with a new car. Maybe the compromises are big ones like, “This car is too expensive. I need to go get the gray car without the leather trim, instead,” thus blowing up the whole process and starting over. Or maybe the compromises are more subtle, like cancelling your satellite TV subscription in favor of over the air channels to free up more money in your monthly budget to pay for your car loan. Every decision, every step somehow involves a compromise.

Money and goods are in limited supply, and so you’re constantly making tradeoffs between what you have, what you need and what you want. I’ll buy that new chair for my office today rather than the Nintendo Switch I’ve been coveting because I have a limited amount of funds available. I value a comfortable chair I use every day over playing Mario Kart. In my ideal world I’d have it all. No compromise would be required, and it’d be even better if I didn’t have to work for it either. That’s just not the world we live in.

Everyone budgets, even if they don’t think they do. Maybe you don’t have a spreadsheet or fancy app to categorize and track your spending, but you’re still going through the budget process in your life. The loan example earlier is crude budgeting because it’s calculating a decision to spend funds. That’s really what budgeting is, calculating what to spend based upon compromises.

When we attempt to budget without compromise, bad things tend to follow. We buy a car we can’t afford and we default, resulting in it being taken away from us. Or we don’t pay that credit card off fast enough and attempt to buy food and when we have no credit left we end up not able to feed our families. Compromise is ultimately the curb that hones in responsible purchasing decisions. That curb is based off of consequences, which are critical. They are the thing that gives us pause when we don’t want to compromise.

Curbs are good, they keep cars on the road. Curbs provide the external boundaries for our path forward. This is the function of compromise, and our budget is really just that road we’re cruising down from month to month.

Want to hear more budgeting banter? Check out Episode 25 of Life with a Twist of Lemon.


React, Relay & Mutations

by Stan Lemon


A working example of what I’m going to describe here can be found at https://github.com/stanlemon/example-relay-app.


For awhile GraphQL has looked interesting to me, like something I wanted to learn. I love the concept of strongly typing expressive queries that can be batched into a single request. That’s GraphQL, a technology that really seems to shine in UI work for single page apps (SPAs).

Relay is Facebook’s GraphQL framework for React, it’s really where GraphQL got its traction from. I love React and spend a good portion of my hobby time building stuff with it, so GraphQL was a natural progression for me. The problem is that documentation and examples on how to use Relay are all over the place and it’s even harder to get into if don’t already have a working GraphQL server. Some might point out that Apollo is a much easier place to start with React & GraphQL and that definitely seems true, but I specifically wanted to familiarize myself with Relay.

My first challenge was a working GraphQL server that I could issue queries against. Fortunately PostGraphile] makes this super easy. You need a Postgres instance to get going, but after that you have a working GraphQL server over top of a Postgres database. I won’t go into how to setup PostGraphile, it’s documentation is actually rather than good and there are some additional environment notes in the repository with my example code.

Querying from within Relay is pretty easy and straightforward and the documentation that Facebook offers is adequate. If you want to play around with querying check out this GraphQL playground with Star Wars data, it’s pretty fantastic! GraphQL is not just for fetching data though, it also allows you to create, update and delete it. Those operations are called mutations and their documentation is a lot less clear.

A mutation in and of itself is not complicated, there are really two parts to it: (1) the mutation definition and then (2) committing the mutation to the GraphQL server. That looks like this:

import { graphql, commitMutation } from 'react-relay'

const mutation = graphql`
  mutation AppCreatePersonMutation($input: CreatePersonInput!) {
    createPerson(input: $input) {
      person {
        id
        firstName
        lastName
      }
    }
  }
`

commitMutation(environment, {
  mutation,
  variables: {
    input: {
      person: {
        firstName: "Stan",
        lastName: "Lemon"
      }
    }
  }
})

In the app I built I had already loaded all of the person records from my database using a query like this:

query AppQuery {
  allPeople {
    nodes {
      id
      firstName
      lastName
    }
  }
}

When I first got this working I naively expected the properties in the react component that came from this query to update, such that my new person would appear in my list. But alas it did not! Updating the state store for relay is not straight forward. The mutation documentation on relay’s site has some clues, but I ended up struggling to implement what I thought was a pretty straight forward user case: updating the list of nodes from my initial query with a new record.

Make sure your createPerson() mutation is returning the same fields as your allPeople query, and also make sure that allPeople is returning id. Matching fields in the response is important for new records. If you’re only doing updates you can get away with returning just the fields you’ve changed, but the example below does not cover partial updates. The id field is not actually required for create mutations like this, but as soon as you start working with updates you’ll thank me as the the global graphql id is the easiest way to yank an existing record out of the store.

What we need to do now is define an updater function on that the second parameter to commitMutation(). This updater receives a single parameter, the store and this is where we will do our handy work.

Inside the updater function the first thing we want to do is get the portion of the store where allPeople is at, because this is what we need to modify. We need to put our new person into the list of person records in that part of the store, which will in turn trigger the update to our UI. This is actually pretty easy to do as long as you know the key to pass the get() method. I found this out using the replay-devtools, which I highly recommend installing.

const allPeople = store.get('client:root');

Now we have the container of the query. Because we’re using PostGraphile everything is nested under nodes so we actually need to yank that out from under our allPeople variable. That looks like this:

const nodes = allPeople.getLinkedRecord('allPeople').getLinkedRecords('nodes');

We also need to get the person record that our GraphQL server returned to us and then yank the payload from it. The payload in this case is that new person we created.

const payload = store.getRootField('createPerson');
const newPerson = payload.getLinkedRecord('person');

We have the original list of persons and the new person we added, now we need to combine them, this is really easy using the spread operation:

const newNodes = [...nodes, newPerson];

Now we have the full list of person objects as they exist in our database. Keep in mind if you were sorting these somehow with graphql you will need to insert the newPerson into the proper place, not just blindly at the end like we are doing. Lastly we take that new nodes list and replace it in our allPeople portion of the store like so:

allPeople.getLinkedRecord('allPeople').setLinkedRecords(newNodes, 'nodes');

Once this is done the local store in your react component will re-render with the new data.

Keep in mind, this is a root level scenario for the component in question. It seems pretty simple, but good luck finding an example that works like this one. If you’re using data nested under another object (like comments on a post) than there are plenty of examples on the web more suited to that scenario, examples that involve things like the ConnectionHandler.

You can find all the code for my working example over at https://github.com/stanlemon/example-relay-app


Gillette Won

by Stan Lemon


I do my best to avoid social media, and even when I do participate I consume a pretty narrow set of content. For example, my twitter is highly curated to focus on Indianapolis municipal happenings, Apple product rumors and javascript news. On the rare occasion I login to Facebook it’s mostly to respond to messages on my podcast page or to look at old pictures of Chicago North Western trains. I rely on my lovely wife and podcast cohort Jon to keep me in the know on the latest and greatest internet fads, at least the ones that stir up enough trouble to warrant a text. It really is a top notch curation system.

This week the Gillette “The Best Men Can Be” commercial somehow bubbled its way up into my view and I read reactions from both the political left and the political right on how wonderful and how terrible this commercial is. If you’re not familiar with the video you can find it on YouTube. Like so many things today it yielded truly polar reactions. Those that loved it applauded it for calling out what some refer to as “bro culture”. Those that hated it claimed it vilified all men universally.

Here’s what annoys me about this whole thing: Gillette won and everyone else lost. Anyone who thinks Gillette was somehow in pursuit of altruism forgets the age old axion that “any press is good press”. Gillette is owned by Proctor & Gamble, a behemoth of consumer goods based out of Cincinnati. It is a publicly owned and traded company whose sole purpose is to generate profits for its shareholders. Let that set in a minute. Gillette exists to make money, plain and simple.

In 2015 Gillette was the #1 shaving company in the United States, holding onto 64% of the market with runner up Schick. By all accounts both Gillette and Schick make crappy shave products. Both companies sell dull cartridge blade systems that generate an absurd amount of waste, but I digress. In recent years, Dollar Shave Club encroached onto Gillette’s market share by more than a razor’s edge, resulting in a 1 Billion dollar purchase by Unilever. Even beyond sub par subscription services like Dollar Shave Club, you have stores like The Art of Shaving popping up everywhere and a general interest in the more classical safety razor genre of equipment. All this is to say, Gillette is hurting. Its relevance is shriveling up and it needs some life kicked back into its blood. Don’t believe me though, take a look at Procter & Gamble’s stock prices. In a hugely volatile year on the stock market $PG is basically untouched. That’s not what share holders want to see, they want growth!

Gillette has to be loving all the PR it’s getting. Again, any press is good press. People who weren’t talking about Gillette are now, and a product that was not memorable is now gliding its way onto everyone’s social media feeds. So if you loved the video, maybe you’ll go out and buy some Gillette razors in support of the company and its bold position in this video. That’ll help Procter & Gamble’s quarterly sales, and that’s exactly what they want. Or maybe you hated the video, feeling like it unilaterally vilified half the population with stereotypes. If Gillette is lucky, you took to social media to complain about it, or shared some article or other post and further perpetuated their ad campaign. The best advertising is free, and you played right into Gillette’s hand. Either way, Gillette is on everyone’s mind, and that imprint will linger for a bit.

It really doesn’t matter where you stand on the issue, because in the end Gillette won. Nothing has changed, we’re just as angry and polarized as we were before the campaign, if not more so.

Gillette is in good company though. We hate to admit it, but this sort of appeal to our heart strings style advertising - which has absolutely nothing to do with the product being sold - is increasingly common. Tune in on a Sunday and the NFL is talking up fighting cancer and other diseases as well as supporting the military. Don’t be confused that these are somehow honest appeals. At the end of the day it’s just another ploy to get you to tune in and watch the real product, a football game. If you support our military and it appears like the NFL does, you tune in to support them, thus increasing their viewership and further increasing the cost of advertisement on one of the sacred NFL commercial slots. That’s the end goal of these heart string campaigns.

Don’t get me wrong, there are honest folks who mean well by participating in these campaigns their companies put on. I really don’t mean to discount the intent of both NFL players and Gillette employees, I just think we need to be honest about what drives campaigns like this. As much as I would love for it to be, it’s not altruism. We shouldn’t somehow project that onto the marketing departments of these big economic machines who ultimately have dividends to pay every quarter.


On an unrelated note, if you are either thinking of buying Gillette products because you loved the video or if you are thinking of no longer buying Gillette products because you hated the video let me take this opportunity to appeal to you. There’s a better way! Get yourself a good ol’ Merkur safety razor and some Astra blades and enjoy a better shave. Chances are you’ll support a smaller business in the process too, winning all around.