Developer Laptop Contenders, 2019

I had thought that my days of picking laptops were behind me when the Macbook Pro Retina won as The Best Polyglot Platform for the Money. It really wasn’t a contest. The only deficiency the Mac had was multiple monitor support; and that’s gotten a lot better over the years.

The reign of the MacBook Pro has ended with the advent of the Fourth Generation MacBook Pro line. Between the issues with the Keyboard, the lack of ports and requiring dongles for the most basic attachments (like connecting a USB keyboard to the USB-C port), and the fact that the power connector is no longer magnetic, the laptop is almost unusable from a developer’s perspective.

This is not easy news for me to take, as I’d really want to be able to use a Macbook now that I’m on my own, but I can’t in good conscience drop $5,000+ on a laptop that has these issues. And so, I’m in the market for a new laptop. I have my eye on three choices:

Dell XPS 15 (9570)

The Dell XPS 15 9570 is a solid Laptop. It even has the Stack Overflow seal of approval. One strange thing about it is its webcam placement. The webcam is located at the *bottom* of the monitor, not its top. It is the most economical of the choices; with the only downside that if I want an UHD display, I have to give up 16 GB of RAM. When I tried to customize it with UHD and 32GB of RAM, it wouldn’t work. That’s a bummer, as I think 32GB is a safe minimum for development.

Cost: $2389.99
Processor: Intel Core i7-8750H 6 Core (2.20 GHz up to 4.10GHz with Turbo Boost, 9MB Cache)
Memory: 32GB DDR4 2666 MHz
SSD: 512 GB SSD, M.2 PCIe-NVMe
Display: 15.6 FHD (1920×1080)
Graphics Card: NVIDIA GeForce GTX 1050Ti 4GB GDDR5

Alienware M15

Alienware is owned by Dell, and it is primarily a gaming laptop. As a developer, I’m OK with a gaming laptop, as they are generally better made than their business counterparts. I’m also OK with an advanced graphics card — not because I necessarily *need* one (though I would like to drive 4K displays); but because if I’m going to spend the money I might as well get a good value for my money. Some of the cons on the PC Mag review make me pause, especially around the touchpad. Overall, this laptop has a good monitor resolution, good sized ram, and isn’t too expensive for the option.

Cost: $4249.99
Processor: Intel Core i7-8750H 6 Core (2.20 GHz up to 4.10GHz with Turbo Boost, 9MB Cache)
Memory: 32GB DDR4 2666 MHz
SSD: 1TB SSD, M.2
Display: 15.6 UHD (3840×2160), 60Hhz Anti-Glare IPS
Graphics Card: NVIDIA GeForce RTX 2070 Max-Q 8GB

Legion Y740

The Lenovo Legion rounds out the top three contenders with its rather inexpensive (and yet strangely well packed) offering. In fact, it’s so well packed and so cheap that I’m a bit worried about buying it. The only difference between this and the Alienware is the Alienware has a bigger SSD and has a 4K display. Otherwise, they’re identical, spec-wise. The biggest concern is the battery is only 57Wh, which limits the amount of non-plugged in time I can have.

Cost: $2469.19
Processor: Intel Core i7-8750H 6 Core (2.20 GHz up to 4.10GHz with Turbo Boost, 9MB Cache)
Memory: 32GB DDR4 2666 MHz
SSD: 512 GB SSD, M.2 PCIe-NVMe
Display: 15.6 FHD (1920×1080)
Graphics Card: NVIDIA GeForce RTX 2070 Max-Q 8GB

Macbook Pro Retina (2018)

I’m including this because I feel like I have to. I’m not jazzed about spending this amount of money on a system with keyboard issues that only has Thunderbolt ports, and doesn’t have any of the things that really sold me on the original Macbook Pro Retina series. It’s still a contender, but it’s at the bottom of the list.

Cost: $4628.00
Processor: 2.9GHz 6‑core 8th‑generation Intel Core i9 processor, Turbo Boost up to 4.8GHz
Memory: 32GB DDR4 2400 MHz
SSD: 1TB SSD
Display: Retina Display (UHD)
Graphics Card: Radeon Pro Vega 20 with 4GB of HBM2 memory

What do you think? Which laptop should I choose? Do you have any experience with these laptops? What was your experience? Share your thoughts on these contenders and your thoughts on a good developer laptop in 2019.

A better alternative to Sandwich Feedback

In December 2018, I had the opportunity to attend The Lead Dev conference in Austin, Texas. I was extremely lucky that my then employer also paid for a whole day workshop on becoming a manager through Demystifying Management by Lara Hogan (@lara_hogan ). It was a wonderful full day workshop, chock-full of lots of useful advice for the aspiring manager. One particular management technique she taught has stuck with me.

Instead of “Sandwich feedback”, where the giver gives feedback in the following pattern:

  1. Good Thing you do.
  2. Bad thing you did that needs correcting.
  3. Good Thing about you.

Lara suggests the following format:

  1. Observation: A by-the-numbers recounting of the behavior you witnessed that you want to give feedback on. It’s important that this observation be devoid of emotion or parsing. It should be the same observation that a camera would pick up if it were recording the behavior you’re speaking towards.
  2. Impact: How did that behavior affect you? What did you feel as a result of it? How did it affect others?
  3. Open-Ended Question: At this point, ask an open-ended question (a question that cannot be answered with a “yes” or “no”, and it should be a non-hostile question). Lara suggests one of her favorite, “What are you optimizing for?” The Open ended question allows for a non-amygdala-hijacking response. One other piece of advice she gives is to make it a genuinely curious question. Use this moment to understand what drives the other person, and what caused them to take the action they did.

If you get the opportunity to attend one of Lara’s workshops, I highly recommend it. For my part, I strive to use this feedback format in all my interactions.

Looking back at Some of the Changes in C# 6

We’re currently on C# 7.4 and approaching C# 8 (Wow!); but C# 6 was the first version of C# post Roslyn (Compiler rewrite, to oversimplify it a bit). C# 6 was the first version of C# to coincide with .NET Core, and so it’s where the development of C# seemed to… skyrocket. I’m revisiting changes to C# starting particularly with C# 6. C# 6 has been around since 2015; and arguably represents the first time core features of the language have changed since 3.0.

C# 6.0 unveiled several language features that are useful for removing verbosity from common class operations, and set the groundwork for future improvements that we’re only really scratching the surface of.

Readonly Auto-Properties

Prior to C#6, if you wanted to make a “read only” property, the best you could do was:

public class M1 
{
public string P1 {get; private set;}
public M1()
{
P1 = "hi there";
}
}

There were a few problems with this approach.

First, if M1 implmented an interface, you couldn’t use a private accessor. Second, the string P1could still be mutated inside the class; probably not what you wanted semantically.

If you forsook auto-properties entirely you’d be fine, but that’s going in the wrong direction:

public class M1 {
private readonly string p1;
public string P1
{
get { return p1; }
}
public M1(string text)
{
p1 = text;
}
}

With a readonly auto-property, you can now have reduce the above sets of code to this:

public class M1
{
public string P1 { get; }
public M1()
{
P1 = "hi there"; //can only be changed in constructor!
}
}

This improved syntax allows you to semantically and concisely declare your intent for a property: That it should be set at construction and not changed. It is immutable. This is extremely useful in the following situations:

  • For read only DTOs (Data Transfer Objects), getting data from the database for display where it wouldn’t make semantic sense for an implementor to try to change the value; or for ViewModels.
  • For a public value that will be set at construction and should be able to be referenced by other classes throughout the application in an easy manner.
  • For immutable objects. Immutable objects are easier to reason about and interact with.

Property Initialization

This feature in itself is pretty cool; but what if you don’t want to create a default constructor just to deal with creating an immutable property? You can now combine property initialization (a la field initalization) with readonly auto-properties:

public string P1 { get; } = "hi there";

This reduces the use of a default constructor just to set this property; and it ensures that no matter which constructor is used, this property gets set.

Expression-Bodied Members

These changes to C# are neat; but if you wanted to have more complex logic inside your getter; you were stuck using the ‘old’ style properties:

public class M1
 {
   public string P1
   {
     get 
     {  
         DateTime.Now.Month == 11 ? return "Month Left" : return "Months Left";
     } 
   }
 }

With C# 6, you can change this to a single line of code:

public class M1
 {
   public string P1 {get; } => DateTime.Now.Month == 11 ? "Month Left" : "Months Left";
 }

The biggest change here is the use of the Expression Body syntax (which would later be expanded in C# 7); and that there’s no “return” in this expression. This mimics the closure syntax used by LINQ.

Expression-Bodies can also be used in methods in C# 6:

public class M1
 {
    public string GetMonthPluralText() => DateTime.Now.Month == 11 ? "Month Left" : "Months Left";
 }

Null-Conditional Operator

The next ‘big’ feature in C# 6 was the change to how null checks were handled. Prior to C# 6, if you wanted to check for null, you had to do something like the following:

public class M2
{
public int? P1 {get; set;}
}
public class M1
{
public M2 M2P1 {get; set;}
}
public int GetValue(M1 m1)
{
if (M1 != null && M1.M2P1 != null && M1.M2P1.P1 != null)
{
return M1.M2P1.P1.Value;
}
return 0;
}

Ok, ok, so this seems like a convoluted example. I’ll give you that. But in order to successfully determine if class member property P1 of class M2 has a value, you have to check its parentage *first*. If anything in the chain of calls is null, you’ll get a NullReferenceException. That would be bad.

C# 6 fixed this by allowing the use of a new operator, the null-conditional operator. So that the above code becomes:

public int GetValue(M1 m1)
{
if (M1?.M2P1?.P1 != null)
{
return M1.M2P1.P1.Value;
}
return 0;
}

This is far more concise, though I’d argue that it’s not really clearer to a casual observer what’s going on.

If you read code long enough, you don’t really “read” the code any more, you skim it. With less concise code; it’s easier to ‘see’ mistakes when skimming, for instance if you leave out a null conditional check. With the ?. syntax, there’s no easy way to see that you’ve forgotten to make a null check: M1.M2P1?.P1 != null but overall it’s been a solid addition to C#.

When C# 6 came out I was quite against the Null conditional operator and the expression-body syntax; but after a few years of using them, I am happy to have them in the language.