Solution to Your Law of Demeter Code Smells

Sometimes you write code that you’re not too proud of. It’s just too easy to chain a bunch of methods together. However, that’s in violation of the Law of Demeter. Like all design principles, this law helps us write code that is maintainable and adaptable. The basic gist of the Law of Demeter is that any object should assume as little as possible.

- Each unit should have only limited knowledge about other units: only units “closely” related to the current unit.
- Each unit should only talk to its friends; don’t talk to strangers.
- Only talk to your immediate friends.

An object shouldn’t have to reach through another object to call a method. There are times that we really can’t get around this. Take the example below. We have a gift class that belongs to a giver and a receiver. We need to know the full name for whom the gift is for.

1
2
3
4
5
6
7
8
9
10
11
12
class Gift
  belongs_to :giver, class_name: "User"
  belongs_to :receiver, class_name: "User"
end

class User
  attr_accessible :first_name, :last_name

  def full_name
    "#{first_name} #{last_name}"
  end
end

How do we avoid doing something like this: gift.receiver.full_name? With the help of delegate from Rails, we can refactor things to look more like this.

1
2
3
4
5
6
7
class Gift
  belongs_to :giver, class_name: "User"
  belongs_to :receiver, class_name: "User"

  delegate :full_name, to: :giver, prefix: true
  delegate :full_name, to: :receiver, prefix: true
end

Adding the prefix: true option means now we can call gift.receiver_full_name. This brings the knowledge of the method full_name closer to the gift object, so now it is rightfully be able to call the method without violating the Law of Demeter.

Lifehacking Your Commute

I’m not a fan of commuting. Little did I know how spoiled I was in NYC, never living more than a 1.5 mile radius from where I worked. Now my commute is anywhere from 65 minutes to 2 hours one way. But enough about my commute! We are here to talk about how to make it better.

Like a lot of nerds out there, I’m all about productivity. At the office, we all took personality tests, that were based off of Myers-Briggs. The results pointed out that I am motivated by novelty and excitement (duh) and I’m always picking up new skills. Sounds about right! This blog has been documenting my progression as a software engineer. It only makes sense to use my commute time as another opportunity to get better at coding.

The trick is to already have a game plan before you start the commute. Once you get on the train, or start driving, it’s too easy to turn on the music or incessantly check facebook. Be realistic about your game plan. In the morning, you may be able to read a heavy duty programming book, but on your way back you just need to chill. Listen to a podcast then.

Podcasts

They’re a great way to get an overview of technologies you’re not familiar with. My favorites are:

  1. Ruby Rogues
  2. The Changelog
  3. Giant Robots Smashing into other Giant Robots (from Thoughtbot)

Books

The train ride is dedicated alone time. Without a commute, I’d never read as much as I do now. My current read is Head First Java. Turns out, learning an additional language isn’t that hard. More about that in a different blog post.

Pocket

Loooooove Pocket. This is how I do most of my internet reading, sans annoying ads. When Ruby Weekly comes out, I “pocket” the articles I want to read. I also have some IFTT recipes to fill my Pocket with my favorite blogs. Pocket strips all the extra stuff away and delivers the content in an easy to read format.

Coursera

Coursera is an online education platform where you take courses from well known Universities for FREE. You can choose from their many computer science courses, where you’ll have access to video lectures, problem sets, quizzes and even a final exam. The student forum discussion is also helpful. You don’t even need to be in front of your computer to get through the course! All you need is a smart phone. Coursera has a great iPhone app, which is how I watched lectures on my train rides.

Reset Time

Commuting might be your only alone time to decompress. Taking breaks can actually help you be productive and increase creativity, according to this article. The last thing you want to do is brun out. Give that brain its rest.

Converting to Vim

I remember the first career fair that Flatiron held, somebody asked a fellow student what their favorite vim shortcut was. When he admitted to not knowing what vim was, the potential employer turned around and walked away. It was a blessing in disguise. You don’t want to work for closed minded managers that would correlate knowledge of vim to programming potential. Nevertheless, the memory stuck in my head, and I wanted a chance to try for myself. Almost two years later, I’ve finally taken the plunge.

Why Use Vim?

The mouse or touchpad is bad. The single repetitive motion the mouse asks of you, carries tension all the way up to the base of your neck. I’ve tried countless ergonomic solutions. None have worked for me. I end up with a stiff neck and have to turn my whole body to talk to someone. The mouse is also SLOW. During my finance internship training years ago, they took the mouse away and had me build spreadsheets, timed. I love keyboard shortcuts and that’s all vim is. A text editor chock full of shortcuts. Oh yeah, and almost every computer has it built in already. No need to get a license and install. It’s open source! Tons of plugins at your disposal.

How I Made the Leap

Before I installed every plugin known the earth, I started with the bare basics. Borrowed heavily from @rheaton, you can copy my .vimrc and plugin setup here. Follow the README for setup instructions.

Next, I ran vimtutor straight from the command line for a great interactive tutorial. Vim Adventures is another great one to build up that muscle memory. And of course, I watched Upcase’s vim online tutorials

Shortcuts I use regularly

As you go along your normal text editing ways, you may notice yourself doing repetitive tasks. Write it down and google or ask someone if there’s a faster way via vim. Then add the shortcut to your cheat sheet. Pair programming also helps, by observing what shortcuts they use. Just like learning to type, the shortcuts will become part of your muscle memory. Here’s my list.

Pane Navigation

  • Ctrl + w + w: switch panes
  • Ctrl-w + s: horizontal splitting
  • Ctrl-w + v: vertical splitting
  • Ctrl-w + q: close pane

Search and/or Replace:

  • :%s/what i want replaced/newtext/gc
    • g is multiple times per line
    • c is confirm
    • gcc instead of gc if you don’t want to confirm
  • /search_for_this_text
    • n: go to next match
    • N: go to previous match

Navigation:

  • h, j, k, l: your arrows on the home keys (for more daring fun, completely disable your arrows)
  • Ctrl + ^: beginning of line
  • Ctrl + $: end of line
  • w: until the start of the next word, EXCLUDING its first character
  • b: beginning of previous word

Formatting:

  • V: select whole lines
  • v: in select mode
  • Ctrl+ v: visual block mode, select vertically
  • indenting multiple nested blocks: highlight block of text, then =
  • ~: toggles case

Nerdtree:

  • \: access nerd tree
  • m: nerd tree menu
  • shift + \, shift + r: refresh nerd tree

Practice!

There is something to be said of wisdom from experience. I’ve always been quick to jump into things, but I’ve come to realize, sometimes you need to slow down now, to be faster later. So just jump in and start doing it! It will take less than a month before you feel completely comfortable, which isn’t that long in the grand scheme of things.

This blog post can help get you started. My list above only scratches the surface of vim’s power. Very soon, you’ll be combining operators and motions, and tapping away blazingly fast!

Yield Confusion

Photo from Free Images

You’re not alone if you’ve been thoroughly befuddled with yield statements in code. Ruby is incredibly semantic, but not all the time. One way of thinking about yield statements is to compare it to driving. When you merge onto the highway, you must yield to oncoming traffic. Essentially, you let the other car go first, unless they’re way behind you, which in that case, you don’t care. In ruby code land, a method executes each line of code, until it reaches the yield statement, then it lets the block go first, before the rest of the code is executed.

1
2
3
4
5
6
7
8
9
10
11
12
def my_yielding_method
  puts "I love cats"
  yield
end

my_yielding_method do
  puts "i love dogs"
end

I love cats
I love dogs
 => nil

You can also pass in parameters into a yield statement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def my_yielding_method
  puts "I love cats"
  yield("sometimes")
end

my_yielding_method { |word|  puts "I love dogs #{word}" }

I love cats
I love dogs sometimes
 => nil

my_yielding_method { |word|  puts "I love people #{word}" }

I love cats
I love people sometimes
 => nil

my_yielding_method { |word|  puts "I love working #{word}" }

I love cats
I love working sometimes
 => nil

Similar to driving, yield statements are all about right of way. It means the block of code outside the method has right of way. After it has finished, the rest of the method may proceed.

Service Objects

As a project grows in lines of code, you may feel icky. Your code feels bloated. You can’t find certain methods. Everything just becomes a mess. It probably feels gross because you know about the Single Responsibility Principle. It states that everything in your code should be responsible for one thing only. Every method should be doing one thing. Every model should be doing one thing. Every controller action should be doing one thing. So you start pushing logic out of the views and into the controller. Then your controllers become 100 lines long. So you start pushing the logic into the models. Now your ActiveRecord model becomes hundreds of lines long, and it feels like you’re stuck with the same mess, just in a different place.

Why should you care to organize your code? To be kind to your future self! Your future self is only going to look at this code again for two reasons: because another feature is being added on OR there was a bug. Your future self does not want to wade through a spaghetti of code. You future self wants to be relaxing next to the pool, sooner rather than later. If your current self pays a little attention to code design and keeps things organized, your code becomes easily extendable and easily testable, and your future self will be happier.

In the code base I’m working on, there was business logic, that was transactional in nature, living in our ActiveRecord models. We had a Subscription resource that was responsible for pausing itself, canceling itself and calculating its own billing cycle. Whew! That’s too much responsibility for one little resource. So we started using Service Objects, like SubscriptionCanceler. Its only responsibility was to cancel the subscription. In fact, we used this naming convention for all our new Service Objects, the object that was being worked on, plus the action that was being done on it.

There were several steps that needed to be taken to properly cancel a user’s account. Each step was a method in our Subscription model.

  1. Invoice the customer any remaining balance
  2. Unsubscribe the user in Stripe
  3. Save relevant cancel information to our database
  4. Trigger a cancel notification

We moved those methods into our Service Object.

app/service/subscription_canceler.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class SubscriptionCanceler
  attr_reader :user, :reason, :subscription

  def initialize(subscription, reason)
    @subscription = subscription
    @user = subscription.user
    @reason = reason
  end

  def run
    return if subscription.canceled?
    invoice_remaining_balance unless box_returned?
    unsubscribe_in_stripe
    ActiveRecord::Base.transaction do
      close_open_invoices
      set_cancel_info
      trigger_cancel_notification
    end
  end

  private
  def invoice_remaining_balance
    ...
  end

  def unsubscribe_in_stripe
    ...
  end

  def close_open_invoices
    ...
  end

  def set_cancel_info
    ...
  end

  def trigger_cancel_notification
    ...
  end

  def box_returned?
    ...
  end
end

Now, our old subscription model would replace all of its cancel related logic with one little method.

app/models/subscription.rb
1
2
3
4
5
6
7
class Subscription < ActiveRecord::Base

  def cancel
    SubscriptionCanceler.new(self, reason).run
  end

end

This also meant our specs wasn’t a bloated mess either. We only have one spec related to cancels. Hurray! My future self is at peace now. Special thanks to @raybizilla for turning me on to this new way of code.

Recursive Algorithms

I signed up for Stanford’s online course, Algorithms: Design and Analysis Part 1, via Coursera. For those people with less traditional comp sci backgrounds, there are plenty of resources to get you up to speed. Lifehacker referenced a list of free, online courses, that would be the equivalent of a bachelor’s degree in computer science. I chose to start with algorithms. This seems to be the weakest point of self-taught programmers because you honestly rarely have to use it. It also happens to be one of the favorite type of problems interviewers like to ask.

I wanted to blog about the merge sort algorithms we’re learning in class or the problem sets I’m working on, but Coursera has a strict honor code that prevents me from facilitating other students from cheating. Instead, I’m going to talk about how to approach those dreaded interview questions that need to be dealt with using recursion. Most of the time, interviewers won’t even say they’re looking for recursion. They’ll just say something like, write me a method that outputs this. But if the output depends on the answer to a simpler instance of the input, you’ve got yourself a recursion question.

Here’s how to approach the problem:

  1. Identify the input. It might be an array, string or number. Usually the problem will be framed something like, “Given a number n … blah blah blah”. So n is your input and you know it’s a number. You might want to ask the interviewer to clarify. Is n a positive integer or is it a float?

  2. Identify how an simpler instance of the input would be helpful. If your input is an integer, the smaller instance of the problem could be n - 1. If your input is an array, a simpler instance could be a subarray of the original array.

  3. Identify the base case. The case where there does not exist a simpler instance of the input.

  4. Write the method, using recursion. A recursive method calls itself with a simpler instance of the input.

Example Interview Question: Write a method that given the index n, output the value in the Fibonacci sequence. The Fibonacci sequence goes something like 1, 1, 2, 3, 5, 8,…

Step 1: The input is n, a positive integer that represents an index.

Step 2: Any value in the Fibonacci sequence is the sum of the previous two values in the sequence. We need the output of n - 1 and n - 2 to calculate n.

Step 3: The base case is at index 0 and 1 because n - 2 for both indexes would result in a negative number, which we know are invalid inputs.

Step 4: Use that recursion magic. Voila!

1
2
3
4
5
6
7
def fibonacci(n)
  if n > 1 # not the base case
    fibonacci(n - 2) + fibonacci(n - 1)
  else
    1
  end
end

One of the reasons why recursion is difficult to understand is our inability to follow how many times the method calls itself till it gets to the base case, then bubbles back up. Seeing a recursive method can leave us questioning, does this really work? I find that starting with a couple steps above the base case will usually help validate the method works. Then, like the comic above, I cross my fingers.

Adventures at RailsConf 2014

My first RailsConf was a relief. For a long time, I’ve felt like an outsider, someone still trying to be a programmer. I think they call this imposter syndrome. But being surrounded by 1,500 Rails enthusiasts made me realize I’m exactly where I need to be.

The opening keynote speaker by the father of Rails, DHH, kicked off the four day conference with the declaration of Computer Science being detrimental to our community. In fact, he calls it pseudo science, a collection of beliefs or practices mistakenly regarded as being based on scientific method, like fad diets. Juice cleanses, anybody? All these programming “laws” are preached to be our way to salvation, where we can rid ourselves of “dirty code.” And the worst offender? The TDD heretics out there.

DHH is controversial. He struck a chord with many people, and must have alienated half of the attendants. I was thrilled. Not because I think algorithms or TDD are stupid, but because he was breaking the mold of what we think a programmer should be. Since graduating Flatiron School, I’ve heard many people claim they only hire Computer Science majors. I’ve even strongly considered going back to school and getting my Masters in Comp Sci. Paying over $60,0000 to achieve a sense of validation? Yes, I was almost there. My teacher pointed out the root of my problem: finding validation from external factors will always leave me feeling inadequate. What I was looking for, is only something I can give myself.

There was a session at RailsConf about the Imposter Syndrome. 70% of all professionals will feel this at one time in their career. In fact, if you’re introverted and a perfectionist, you’re very likely to experience it. If you’re a high achieving woman, even more so. I was expecting to feel like an outsider at the conference. Instead, I found a lot of people like me, curious, clever and eager to help. I was honestly surprised by how friendly everyone was. Not once did I feel uncomfortable being one of the few females there. It seemed that many were going out of their way to be extra respectful because of this fact.

When I started my journey to start programming, I luckily chose Ruby on Rails. Coding in Ruby is eloquent. Building apps on Rails is fast. The Rails community? It’s inclusive and supportive of even someone like me.

Don’t Be Caught by These 3 DateTime Mistakes

Almost every single programmer has to deal with DateTime nuances in their app. Here at Bevel, we’re building a subscription based service, and I’ve banged my head against the wall many times. A wise person once said to learn from your mistakes. An even wiser person once said, learn from other people’s mistakes too.

Mistake #3: DateTime Comparisons or Thinking Today is Less than Yesterday

Say you’re trying to query all orders made before today, but should created_at be greater than or less than today?

DateTime is stored as a super long integer in the database, a representation of seconds that has passed since 1970-01-01 00:00:00 UTC. So for example, Jan 1, 2014 happened 1391126400 seconds after midnight on Jan 1, 1970. As we move forward in time, the current time is greater than any time in the past. Therefore, the following is true:

1
2
yesterday < today
tomorrow > today

Mistake #2: Time Zones or Thinking The World Resolves Around You

Ok, what the heck is UTC? And who decided what is Central time? A SF’er recently lamented the fact that every time s/he sets up a conference call, people assume the time zone is NYC. So s/he will ding interviewees for not doing the research of where we’re located. Instead of asking why UTC, just know it is the canonical time zone that you will be dealing with. In Rails, the default setting is to save your DateTime records in UTC. Don’t try to change this. This is universally accepted, and it’ll be easier to calculate timezone differences off of UTC than from your specific time zone. At 4pm out in California, all my scheduling related specs would fail on Semaphoreapp, but they would pass locally. Turns out that it’s actually midnight in UTC, and therefore the next day. One easy way to avoid this is to use Time.current and Date.current, instead of Time.now and Date.today. They will always return the current time/date in UTC.

Tricks and Helpful Tools

Rails comes with ActiveSupport::TimeZone, a nice library of timezone helpers and worth checking out.

When you write your tests, don’t get cute with created_at. Just use timecop. With this gem, you can artificially travel through time, to get a sense how an object’s behavior will change.

Most of our customers reside in the U.S., but on the east coast. Displaying dates that are inherently UTC end up confusing everyone. One easy way to handle this is to specify the timezone that the date is being displayed in. Another is to use jQuery-timeago. This jQuery library determines the timezone on the client side, and displays the date and/or time accordingly. This means you can cache the page, and the time will automatically update. You get readable things like “1 minute ago,” instead of ugly timestamps

Mistake #1: Overlooking Nuances of the Gregorian Calendar

Don’t fall into the assumption that a month is 30 days, especially if you’re in the monthly billing business like us. 4 months out of the 12 have 30 days, 7 have 31 and 1 has 28, well, most of the time. If you assume that all months have 30 days, you will fall into this trap.

1
2
3
4
5
6
7
8
9
> jan_date = Date.parse('Jan 31, 2014')
=> Fri, 31 Jan 2014
> jan_date + 30.days
=> Sun, 02 Mar 2014

> july_date = Date.parse('july 1, 2014')
=> Tue, 01 Jul 2014
> july_date + 30.days
=> Thu, 31 Jul 2014

In the first example, 30 days skips over February. In the second, 30 days isn’t enough to move you to the next.

Because of the inconsistencies in the calendar, there isn’t an elegant method that you can write to handle all situations. ActiveSupport does make a valiant effort to help, BUT beware, write tests for each situation: leap years and the different types of months. DO NOT rely on built in ActiveSupport (do I sound jaded yet?)!

That being said, here is how Rails can help you. Rails is smart enough to know if you want to increment a date by 1 month, what that means. It will always go to the same day of that month. If that day doesn’t exist, like Feb 30th, it defaults to the last day of the month.

1
2
3
4
> jan_date + 1.month
=> Fri, 28 Feb 2014
> july_date + 1.month
=> Fri, 01 Aug 2014

There are some limitations, though, mainly arithmetic and subtraction of time does not always get what you’d expect.

1
2
3
4
> jan_date
=> Fri, 31 Jan 2014
> jan_date + 1.month - 1.month
=> Tue, 28 Jan 2014

Closing Thoughts

Write tests. Bang Head. Try Again.

Redesigning Yoga in the City

I’ve jokingly been complaining about being pixel pushed by design-minded people around me. But of course, even I can’t deny the power of aesthetics. There seems to lack a sense of professionalism if you can’t even get the basics of design. So, I embarked on the journey to redesign my pet project, Yoga in the City, after taking @thoughtbot’s course, Design for Developers.

Yoga in the City Design Brief

The first step was to articulate our goals for the redesign. I equate this exercise to setting your intention in yoga class. Like the lessons taught in Bhagadvad Gita, one of the premiere philosophical books on yoga, your intention determines the outcome. Borrowed from a yoga teacher: if you saw a tree that you wanted to go to. Would you aim for it or would you wander and hope to find it?

A brief summary of the business / site goals. An aggregate schedule of yoga classes, curated by a yoga snob. The app solves the problem of finding fantastic teachers at different studios. It should also encourage me to discover more yoga teachers to add to the list.

The key users. Yogis that are trying to fit their 1.5 hours of refuge into their busy schedules. They are generally young professionals, both male and female, but predominantly female and peeople that are health conscious.

Scenarios in which your app or site will be used. They should be able to get to the site quickly, process the class information easily and add class details to their calendars.

Design style guidelines to follow. Calming, connected to the world.

Design Principles

My friend’s wife is an art scientist. She studies why certain pieces of art are more appealing to others, why some become famous. It turns out there are some basic guidelines anyone can follow. Let’s critique my old design on these.

Alignment The only thing that is aligned on the left side of the design is the word “Yoga” from “Yoga in the City” and the beige schedule block. Everything else is entirely random. Although I had put a lot of thought in the original design to make things easier to read, I mistakenly thought that just meant bigger font size.

Emphasis This one I understood, although it wasn’t executed that well. I chose to emphasize the day of week “Wednesday.” Why? I’m not so sure.

Hierarchy There is an order of importance, that the eye should discern quickly. Given the font-size and colors used, “Wednesday”,the times and the title seem to compete with each other.

Consistency Patterns can be found in art, dance and music. This provides continuity, which people like. Thankully, I had used a template partial for the individual classes, and programmatically created the divs for them. What I wasn’t consistent with is colors and font sizes. They were randomly picked by me.

White Space Not by design, everything is jammed to the left, leaving lots of white space on the right. White space usually gives a feeling of airy quality, but everything still feels squished in my case. I could have used some white space between the elements.

Balance Another principal that we see in dance and music, as well as visual art. My original website is weighted heavily to the left.

Unity Lastly, everything needs to be tied together somehow. This is, perhaps, more of a feeling than a hard rule.

Grid System

According to @kylefieldler, if the question comes up, when should a grid system be used, the answer is always. This immediately reconciles any problems with alignment. There are also a lot of great frameworks to leverage off of. At work, we’re big believers of Zurb’s Foundation. For my project, I wanted something lightweight, and went with Neat. Twelve column layouts are the most popular because they can easily be converted to three or four column sub layouts. With this in mind, I sketched out a few ideas.

   

One of my concerns was being able to view the site on a phone and quickly digest the information, which is why I threw out the traditional calendar grid out the window. I also wanted to play around with a big hero image that would also fit into the grid layout. Although uncommon, I went with a two column layout, that would collapse into one on mobile.

Typography

Oliver Reichenstein wrote Web Design is 95% Typography and I think most design nerds would agree. Who would have known so much personality can be expressed through a typeface? In this part of the course, we looked at the effects of line-height, line length, letter-spacing, and even the components of the font. Usually, there is more than one typeface on a page, a serif and a sans serif. It’s important to find something that complements and contrasts with each other. You can try the typography dating game.

Color

Color can have different meanings in different culture. Case in point: red is considered bad luck on a trading floor. However, for Chinese people, red represents luck. So knowing the viewers and how they’ll interpret color is important. In America, blue is considered stable and professional. Red is considered dynamic, but sometimes dangerous. In my current redesign, I’m letting the backgound image do most of the color deciding for me.

Next Steps

The readability of the class details still needs work. I’ll most likely choose a different typeface and also darken the transparent, black overlay. A friend pointed out to me that she didn’t really understand what the site was about. I probably need more information there. Still a long ways to go. Hopefully, my next blog post will be about how I built the scraper that’s pulling updated schedules and how to deploy a Rails app on Heroku that uses PhantomJS. Stay tuned!

Coding HTML Emails

Emails are still the most direct way to market your product to clients. With an ROI of around 4,300% (according to the Direct Marketing Association), it’s hard to argue against it. So it was only a matter of time that I was tasked to code some emails. I naively thought it would be a simple task. Write some basic HTML/CSS. How hard could that be? But I can’t remember the last time I coded basic HTML/CSS, if ever. I started with ERB templating, and now am mostly in HAML, thanks to @tjhanley. Even the normal CSS I write is (mostly) organized through SASS. So…HTML emails, it makes me shudder just thinking about it.

Here are 5 tips for that next HTML email you need to code.

  1. If you want any styling, it better be in-line CSS. Yes, you heard me right. There’s no way to link to external style sheets. Plus, most email clients ignore style tags. It makes sense because your favorite email client doesn’t want your css possibly interfering with theirs. Thankfully, mailchimp has a nice widget that can help inline your CSS for you.
  2. Tables are your friend. Someone told me tables are very web 1.0 when it comes to design. Well, that’s the world of email. Padding does not consistently work, but cell padding on a table does, specifically td tags. Don’t forget you can nest tables within tables to create columns and such.
  3. Media queries? You can forget about them. 48% of emails are read on mobile devices (source). Any half intelligent company would want their emails to look good on a smart phone. Our favorite Gmail client on iPhone and Android do not support media queries. Bleh. Gmail client on iPhone will resize the email to fit in the viewport, so your layout isn’t distorted, but everything is hard to read. Gmail client on Android will overwrite any table widths to be 100% of the screen, a pseudo-media query. Despite Gmail’s lack of capabilities, build a responsive layout. Check out this list of 32 Responsive Email Templates by mashable.
  4. CSS functionality is severely limited. Display: none will be ignored. Background images don’t work (consistently). Absolute/relative positioning will also be ignored. Use of FONT tags are encouraged.
  5. Code for a maximum width of 600px. Think small. Think simple.

Happy coding! Meow, meow, meow.