Why TypeScript?

This weekend I watched a talk about TypeScript at Nebraska.Code().  The presenter seemed to have a good grasp of TypeScript and was a good presenter.  Sadly, that combination doesn’t always happen.

One thing I was glad about, was that he put up a picture like this:

I immediately thought, “This is going to be good!” as I figuratively rolled my eyes. But instead, he said “This is NOT the problem with JavaScript.”  That comment immediately made me realize that this was going to be a talk that wasn’t going to just bash JavaScript.

And to be fair, he did.  He identified the following problems with JavaScript:

  • No type safety
  • Functional language with inconvenient syntax
  • Object base, not object oriented
  • Few organizational constructs

He then offered the following reasons as to how TypeScript helps:

  • Optional static typing
  • Familiar OO constructs
  • Enhanced functional experience
  • Improved code organization
  • Works w/ existing JS libraries

The impression that I left the talk with was “TypeScript makes JavaScript object oriented.”  The speaker never said this, and I don’t think he even tried to imply it, so it might just be a combination of everything else I’ve heard about TypeScript coming to a head.

After watching this talk, I’m still not convinced that TypeScript is the way to go.  I like ObjectOriented programming. The bulk of my career has been using OO principles (C++ and C#.)  But I’m of the mindset that not every language has to be object oriented. After all, C is not object oriented and it definitely serves a purpose.  That doesn’t make C a bad language. Just as Haskell isn’t a bad language. Just because they are not object oriented. Are they possibly harder to learn? Maybe, or maybe they’re harder to learn only because we’re so used to OOP.

I’m reminded of when I was in seminary. I took 15 hours of Greek and 15 hours of Hebrew. I started with the Greek classes, and they were way easier than Hebrew was.  I had a smart friend who started with Hebrew and he really struggled with Greek. To me, it was strange, because Greek was so much easier to me.  The problem was, he was coming from a different paradigm, a good grasp of Hebrew, to a new paradigm, koine Greek.

I think the same thing is true with programming languages. JavaScript has some problems (tell me a language that doesn’t.) But I don’t think one of it’s major problems is that it’s not OO. I’m also not convinced that it having dynamic typing is necessarily a bad thing either.  However, approaching JavaScript as if it WAS an OO language or that it HAD static typing is going to cause you problems.  In the same way as taking an English sentence and translating it word for word into Spanish is going to sound off or “wrong” to Spanish speakers (if for no other reason that the differences in word order.)

The best example, to me, from the talk about why TypeScript is beneficial was the example of inheritance. For this example, he demonstrated a relationship like “A developer is a type of employee.”  For us OOP folks, we immediately get that. But it’s different in JavaScript because it’s a prototypical inheritance. TypeScript cleaned up that type of inheritance with no problem. The TS code was much smaller and easier to read than the generated JS code. The speaker even commented that in 6 months, when he has to come back and make a change, he’d rather make a change on the TS code than the JS code.  The JS code had 3 or 4 levels of nested functions.  By and large, I would agree. If those were my only two options.  But I feel like that type of solution is missing something.

If someone came to me and described a problem domain with highly related entities, for example, the classical Animal:Mammal:Human hierarchy that is used so often in OOP, my first thought would not be “I know, let’s use JavaScript to model this.”  In the same way that I would not think “I know, let’s use MongoDB to store it.” I guess what I’m saying is, while TS seems to clean up inheritance, a possibly better way(?) would be to use a different language.

And I think that is my biggest struggle with TS. I get that they’re trying to make JS better, much like C++ tried to make C better (and arguably that C# tried to make C++ better.) But the difference to me is that C++ doesn’t compile to C. It’s a different language that generates its own binaries.  I think if TypeScript had native browser support like JavaScript, I would be more prone to adopting it.  But even then, only if it was its own independent language.

Those are just my thoughts. I’ll still keep reading & listening to stuff about TypeScript. I’m sure at some point, I’ll try to write a Hello World type of application. But it’s still further down the list of things to learn for me.

How Do You Use Pull-Requests?

The process on our team is to create a feature branch off of develop, do your work and then push it up to the repo. Then when it’s all done, you create a PR and have someone from the team be the “primary reviewer.”  This person’s job is to review the PR, make sure that you’re doing the right things in the right way, then they have to pull down the branch and test it before they can approve it.

We got to this point after many iterations about how we wanted to do PRs. At first we opened up all the PRs to everyone on the team and after a majority of the people approved it, we would merge it in. Then we found that a lot of people didn’t want to review and the PR process would drag on. Having a PR open for a long time causes its own problems, as by the time the code is ready to get merged, it’s old and often has a lot more conflicts.

Next we tried to only have a couple people PR the code, the “leads” if you will.  However, that didn’t work out very well, as people would often forget to address the comments etc.

We tried PR buddies, and finally came to this incantation.  Despite all the struggles of PRs, everyone on the team seemed to agree that they served an important purpose, and wanted to continue them.

Recently, however, I had a revelation about PRs. I always approached PRs as “Let me review this code to make sure it meets our standards, and is clean and working.”  That would be my motivation, and sometimes I felt like “I just don’t have time to do this PR because I have my own stuff to do.” But then, within the last couple weeks, something dawned on me.  A PR is not just a way for me to make sure other people on the team are doing things the right way (and for them to make sure I’m doing them the right way) it’s also an opportunity for me to learn.

When I open up someone else’s PR, I get a chance to see how they tackled the problem, or how they solved something. Sometimes that’s as simple as seeing them use some new lodash function that I’ve never seen. Other times, it’s seeing a different paradigm or approach to the code. Still, other times, it’s seeing something like a new way to test the code.

I’m a big proponent of writing clean code because I believe that we’ll read our code many more times than we’ll write it.  But it never occurred to me that the first time I’ll read that code is in a PR.  I’d like to say that since I had that revelation, every PR has been walking in the light, but it hasn’t.  I still find myself, at times, looking more to make sure that the code meets the team standards, and forgetting completely that I have a chance to learn.

If your team does PRs, I’d highly recommend trying to take the approach of learning something from a PR, instead of simply judging it.

We Are Learners

I try to not mix my 2 blogs. I have this one, that focuses on the professional side of software development, and I have another blog which follows my Brazilian Jiu Jitsu addiction. The reason is, most of the people interested in software don’t practice BJJ, and most people that practice BJJ don’t care about software.  That said, my worlds collided this week.  I was listening to a podcast, where the head blackbelt at our academy was talking about when he was young. He’d gone out and won a big tournament. He came back to the gym, and told his professor (BJJ term for head instructor) something to the effect of “There’s nobody here for me to train with. I’m better than these guys, I just won this tournament.”  He spent the next hour in the middle of the mat as any and every person at the gym had free reign against him.  The other students were promised advancement for every time they could make my professor submit.  He had one guy ultimately choke him until he passed out. When he came to, he was told that even though he was in his 20s and his opponent was in his 60s, his opponent was a blackbelt in Judo and had been practicing for quite some time.  On the podcast he explained “That’s when I learned that you don’t fight the guy, and you don’t fight the belt, you fight the position.”  Meaning, regardless of who is attacking you, in BJJ, you have to be smart and defend the position. He learned something that he wasn’t planning on learning. He wanted to train with people who could teach him new moves and new techniques. In the end, he learned something much more valuable.

How does this apply to software development? Developers, as a group, tend to enjoy learning. At this point in development history, how could you not enjoy learning? There are new frameworks and libraries being produced by the day (by the hour?) Things are constantly changing. Whether it is new languages, new paradigms, or just improvements in the ones you’re familiar with, there’s always an an opportunity to learn. It’s something that I think drives most of us to fire up our computer every day.

But not all the learning as professional software developers is about what a particular framework can do. The past month or so has been a tiring month on my project for many reasons. Not bad, just tiring. This past week in a developer meeting, I encouraged my team to use these opportunities to learn and grow. We’re using Angular, which is something nobody had extensive experience with before this project, so there’s a chance to grow in that framework. But even more than that, we’re interacting with a domain that none of us have experience with. We’re performing tasks for a client that none of us of have worked with in the past. We have the chance to learn specifically about the domain and about the client. However, we also have a chance to learn about clients in general. How do you handle client expectations? What’s the best way to find out use cases for a system? How do we determine priority based on client feedback (hint: a client will almost never tell you “Do A, then B, then C” so you have to learn to listen and understand what they’re after.)

A lot of things might be considered boring or even “not real work” (which is a phrase that my Project Manager hears me jokingly say way too often.)  But there is not a software project that exists for paying customers that doesn’t have to solve these problems. So we have to spend time & energy learning about them as well. Being a developer doesn’t just mean learning how to program, it means learning what to program as well as when and why to program as well. So even on projects that don’t see technically challenging, there is always more to learn.

After talking about that with my team this week, I came home to a broken toilet. Thankfully, my brother-in-law used to be a plumber, so he tried to help us fix it over the phone. We finally realized the jet at the base of the bowl was clogged, most likely with one of those toilet cleaning tabs.  I didn’t set out the day to learn about toilets, but in the end, learning that 1. they have a jet at the base of the bowl and 2. that if it is clogged, the rest of the unit won’t function turned out to be rewarding as well.

What’s the Point?

For me, this past week was filled with meetings. I had meetings with the client, I had a demo, I had sprint planning, I had a meeting or two on our project plan. I even had a couple meetings with the purpose of helping the people who will be meeting with the client be prepared. In the end, I had about 8 hours of meetings this week. Those are the ones on my calendar. They don’t count the times I had “discussions” with anyone on my team. I spent a lot of time not in my IDE this week.

All those meetings and interactions led to very little time of dedicated development. By that, I mean there wasn’t one day that I had a good 4 hours of uninterrupted development time. Yet I was still able to release two new features this week. I started thinking about how I was able to do that. Study after study shows that switching contexts is expensive, and I can attest that is true, but I was still able to be productive and help move my project forward, not just with designs & client relations, but the product today is better than it was on Monday in part because of the software I wrote.

As I started thinking about it, I examined my motivation and what drives my software development. So my number one goal is “Does this move the project forward?”  Not “Is this a good change” but rather, is it moving the project in the right direction.  Which then lead me to think “HOW do I move the project forward?” The answer to that question was actually surprisingly easy “By completing this story that is in front of me right now.”

However, the question “HOW do I complete this story?” is a bit more complicated. Any story has a lot of possibilities for rabbit trails and diversions. When I sit down to complete this story I could just ignore everything in the project and slap something together. At the other end of the spectrum, I could take time an evaluate the entire project and figure out how make refactorings and then write my project. As is often the case, the truth is probably somewhere in the middle. As I’m working on the story, I’m still asking myself the question “Is THIS moving the entire project forward?” If I can’t honestly answer that question yes with at least a 95% certainty, I don’t do it. Does that mean sometimes I don’t make changes that would be “good”? Yes, it does. But the point is for me to move the project forward.

I think some people that know me and how I write software might be shocked by me saying this. I’m a HUGE proponent of TDD (if you’ve read this blog at all, you probably already know that.) I’m also a fan of clean code and refactoring code. One friend also ribs me about the amount of joy I get out of deleting code (seriously, it’s better than writing code!)

So how can I be such a huge proponent of these aspects of software development that are often viewed as rearranging deck chairs, and at the same time talk about the number one goal of any software development needs to be “to move the project forward?” Simple. I do TDD, refactoring, clean code etc because those help me move the project forward as fast as possible.

There’s a lot of things we can do as software developers. There’s all sorts of practices and patterns that we can implement. But at the end of the day, the customer doesn’t care about the repository pattern, or observer pattern. Often times, they won’t even understand what that is, nor should they. What the customer does care about is a quality working application.

So for me, the point of software development is to deliver a working application. If in the midst of development I’m doing something that does not meet that goal, I stop.

Code Optimization

For starters, a friend reached out to me on Facebook and asked for my thoughts on optimizing code, especially with the cost of hardware being so cheap. I don’t know that this will answer his question, but it’s my thoughts on the subject.

Early Optimization

Premature optimization is the root of all evil (or at least most of it) in programming. – Donald Knuth

That is a rather famous quote that developers use quite often. A lot of times it’s used as an excuse for writing bad code, sometimes, it’s used to remind people to not spend time optimizing their code too early.

Too often developers will spend time and energy trying to lay out the perfect design and perfect implementation because they fear an area of the application will be too slow. Keep in mind, they haven’t tested the performance. They don’t know that it’s a bottleneck, just a hunch that it will cause a problem.  The reason this is bad is that in isolation it’s difficult to tell what will be slow code.  For example, if you’re reading through code and you see something that raises a red flag, you could take some amount of time to resolve that issue. Only after resolving the issue and getting it merged into mainline development do you realize the code you just optimized gets executed one time a week, or a month, or a year. Meanwhile, there is code in the application that gets executed multiple times a minute, or even multiple times a second.  Until you know what the actual bottleneck in the application is, it is irresponsible to try to optimize it.

HARDWARE OPTIMIZATION

That’s the first problem with code optimization. At the other end of the spectrum is a different problem with code optimization. A lot of times this problem starts with a discussion like “Space is cheap” or “RAM is cheap” etc. The thought is, that developers get paid a lot of money. Most of the time a senior developer in the mid-west is making around $50 per hour. However, the total cost of development is usually closer to $75 per hour. And if you’re a consultant, you’re probably getting billed out at $100-150 per hour.  So it doesn’t take a lot of time before the cost of implementation gets pretty high.  For example, instead of paying a developer 10 hours, you could buy a pretty decent server, and the developer could be doing other things.

However, this makes a couple assumptions. First, it is assuming that RAM and CPU solve the problems developers are trying to solve. Sure, RAM and CPU help a lot, and they cover over a multitude of [programming] sins. But they’re not the only systems that could be bottlenecks. For example, network throughput could be a bottleneck. This could happen if an application is sending too much unnecessary data. Instead of sending only the data that is required (e.g. 100 bytes) a developer may send an entire record, 1KB, or 10 times more data than is required. This isn’t solved by building a bigger or faster server. It’s only “solved” by either expanding the network pipe, or by sending less data.

The second assumption this mentality has, is that if a developer delegates performance to a server, that the rest of the code will not have problems. In fact, it’s probably just the opposite. A developer that takes such a lackadaisical attitude to performance, probably isn’t writing good code anyway.

MAKE THE MOST OUT OF WHAT YOU HAVE

While typing this up, I kept thinking about one of the first articles I ever read about Map-Reduce years ago. It discussed how Google used commodity hardware to implement their blazing fast speeds. They did that so that if one of their servers dies, they can easily, quickly (and cheaply) pull the server out of the rack, and throw a new one in and keep running. They did this, not by stock piling a lot of really expensive servers. Instead, they did it by writing code that is optimized for the hardware they had. They wrote frameworks and libraries that realized the bottleneck was serially processing a request when delegating it would be much quicker. It wasn’t that the hardware they had was bad, and couldn’t process a million records, it was that it couldn’t easily process billions of records. However, they realized that if they took those billion records and split them up across 1000 computers, then each of those 1000 computers could easily process a million records.

That is, they matched up the code being written to optimize the hardware they had available. They didn’t buy bigger servers, or more CPU. Instead, they wrote good code to take advantage of what is there.

I will most likely never work on a Map-Reduce algorithm, much less one that will be used by such a large company & most people on the face of the earth. However, that doesn’t excuse me from the responsibility of writing smart software. The application I’m working on right now will be run on a corporate network that I have absolutely no control over. I can’t dictate what the specs of the users’ computers are, nor can I dictate when they should be updated, or even what OS version they’re running.

If I were to divest myself of the responsibility and say “When they upgrade, it will be faster” I’m opening myself up to bad coding practices, and building something that might take an inordinate amount of hardware in order to perform.

Your App Might be Making Your Users Fat

In his book The Power of Habit, author Charles Duhig recounts a series of studies that were done around people’s willpower. Researchers were trying to find out if willpower is like a muscle, something that can be trained. In one experiment, participants were told they were doing research on taste profiles. They were brought into a room and were presented 2 bowls, one had radishes and the other had warm chocolate chip cookies. Each participant was told to only eat out of a particular bowl. That is, each participant could only eat radishes or cookies, and it was determined by the researchers.

After a period of time, the research assistant would come back in and tell the participant that they had to wait about 15 minutes for the next part of the experiment.  In the mean time they were presented with a puzzle and were told to work on it until either they got frustrated and rang a bell, or until the researcher came back in. However, this was not an activity while they were waiting, this was actually the next step in the experiment. The puzzle was literally impossible to solve. Those people who were only allowed to eat radishes spent much less time working on the puzzle before ringing the bell. Additionally, they displayed a much more negative attitude when working on the puzzle, berating themselves for messing up etc.

What the researchers found through this experiment, and others like it, was that willpower is a diminishing resource. That is, the willpower the radish eaters exhibited in passing up the cookies was the same willpower they needed to keep working on the test. Conversely, the willpower the cookie eaters saved by not resisting temptation came in handy when working on the puzzle.

It’s the same reason people tell you to work out early in the morning. By the time you get through a day of decision making and stress at work, you don’t want to go to the gym, you want to go home and relax in front of the TV. If you’re like most people, you don’t even want to go home and cook, you’ll pick something up along the way.

If you think about it, it’s a contributing factor to why diets fail around Thanksgiving and Christmas every year. People have every intention, but as they travel and spend more time with family, stress levels rise (if my family is reading this, not you, obviously, I’m talking about other people.) The stress and little decisions that go into the day of dealing with aunts and uncles and cousins and in-laws and brothers and sisters depletes your willpower and ability to turn down that extra dessert.

So how does this relate to software and your app? Think about the experience your average user has. Are you asking for more information than you really need? For example, if I specify my zipcode, you should be able to know my city. Or if I type in the first 2 digits of my credit card, you should know what type it is without asking me.  Those two are very trivial examples, but the represent two times I have to think & decide “Is it a Visa or Mastercard?”

If your application is presenting your users with a lot of choices, and is not guiding them through the process, you are depleting their willpower, just by using an app.

Wouldn’t it be nice if instead of depleting their resources, we could conserve them? I think we can, but it will take more effort on our role as developers and designers. Try to find a way to guide them through the information you need instead of prompting them with decision after decision.

“What did you learn at the conference?”

This past weekend, I spoke at St. Louis Days of .NET. It was my second time attending and also my second time speaking there. It’s a great conference. I enjoy the location and the people.  The drive isn’t always fun, but this year my wife & kids came along, so that was nice.

As we were leaving the conference and heading home yesterday, my wife & I started talking about how I hate when people ask me what I learned at a conference. I dislike it because it’s rarely something I learned in a particular session. For example, I watched a session on Ember. It was good, the presenter was engaging & energetic. He knew is information, but by-and-large, I didn’t really learn anything I didn’t already know about EmberJS. And that’s ok.

did learn about the audit tab in Chrome dev tools. I also learned how Hadoop got it’s name.  I learned a couple other bits of trivia, we’ll say, at the conference. But to me, it’s not about the sessions necessarily.

I spent 2 days with people that love technology. I hung out with people that are passionate, not only about coding, but about helping other people get better at coding. I was able to “network” with a lot of people. And that was great. I now have connections to more people which lets me see more of what is going on in the industry.

The best part about the networking is that you don’t have to be a speaker to do it. I spent about 30 minutes in the speaker room this time. During that time, I was IMing my team back home asking them how their PRs were going and looking at some things in code.  Once that was done, I left (and that was in part due to the political discussion going on in the speakers room.)  The night before, when I hung out with the speakers at the speaker party, I stayed pretty much with people I already knew.

My point is, speakers are just like everyone else. Even the guys that have a full room or standing room only are more than eager to talk to you. It’s why we do this, we love talking about technology.

So what did I learn? I don’t quite know yet, ask me again in 8-10 months once I get a better feel for how my network grew & changed this weekend.

Why am I not using Yeoman or another generator?

I’ve got a little side project that I’m working on. I have an app at track.couchjitsu.com. It tracks how much time I spend training Brazilian Jiu Jitsu. It tracks when I go to conditioning, technique, sparring or judo. It actually will track anything. I wrote it about a year ago. It’s fairly simple in its current form. It’s a .Net backend with one Angular page, and then a couple Razor pages. It was an app I wanted, and also a reason to use Angular.

I’m currently rewriting it using a MEAN stack (Mongo, ExpressJS, NodeJS, Angular.) I’m planning on adding some features to it, and also making it a true SPA.

There are quite a few generators out there. I can use Yeoman and have a template up and running by typing yo angular  in my terminal. I could also use something like mean.js or mean.io. Both of those are really great. You can have a MEAN app up and running in a matter of minutes (seconds?) They have a nice project structure set up, hooks in place for Passport, a social-sign-on library.

I’ve created sample projects with all 3 methods. Sure enough from installing to having a decent looking UI on my screen was only a minute or two. They have some really nice architecture as well. Patterns I probably wouldn’t have thought of myself. So why am I not using any of these on my side project?

The short answer is “I want to know what I’m doing.” There are a lot of things that I didn’t have to do with those projects, they just magically worked. It made me realize that I wasn’t really developing with node an angular, I was filling out a template. I wasn’t being forced to make decisions for myself, so I didn’t necessarily know what was a good decision or a bad one.

I don’t anticipate doing this every time. For me, it’s more of a one-time-only kind of event. Understand how to set up cookies, or how to handle basic routing, etc. Once that’s established, then I can go back to one of those templates, find the one that fits best with  me and focus on writing the application.  But this time, I need to focus on the mechanics of node and Angular.

Let’s Iterate Fast

We’re 3 weeks in to a new project at work, or in sprint time, we’re half-way through our second sprint. We’ve had a rough go, to get started. Probably not anything worse than most projects. But since this is the first time on a project in this role, I really wanted to get out of the gate strong and impress our clients (and our boss.)  Even though I knew there would be some initial churn as we get servers set up, and the project established, I still didn’t want to deal with it.

It’s been a learning experience, to be sure. One thing I’ve already noticed in the 3 weeks on the project, is that I’m saying a couple phrases a lot. The first one is “Done is better than perfect.” And the corollary to that is “Let’s iterate fast.”  What I don’t mean by the second one is “Hurry up! Just push it out there.” Instead, what I mean is “We know we’re going to iterate on this. That’s ok. We know we’re not going to nail the design the first time. That’s ok as well. We know there are going to be parts of our code we don’t like. That’s ok. Let’s just plan on that, get our code in and when we realize our mistakes, iterate on it.”

Too many times in my career, I’ve tried to get the perfect design, or really, just the right design. I’m too much of a realist to know that we’ll never have a perfect design. What happens, though, is that I spend a lot of time trying to nail down a design that I like, and by the time the project is over, I realize that it’s not very good, or at least I know the pitfalls of that design.

I don’t want to do that anymore. One way we’re trying to help us iterate fast is small stories. So, for example, we had a story that there roles should exist in the API. That’s it, they don’t have to do anything, just exist. Then we had another role that said we should be able to assign features to those roles. Again, assigning features doesn’t have to do anything other than say “Role Admin has the ability to create users.” We don’t need to wire up the ability to create it, just know that it has that ability. We don’t have to know all the roles, or even any of the roles, up front, we just have to know that there are roles and there are features and they need to be assigned to each other.

Another way that we’re trying to iterate fast is by having tests. I have found over and over again, if I have tests covering my code to the point I’m comfortable know that if I make a breaking change they’ll tell me, then I won’t be afraid to refactor.  How does this help? Imagine we have one big data context, it knows about every table in the database. As the project grows, we realize this is too cumbersome. If we don’t have tests we’ll likely say “What are you going to do about it?” But if we have tests, we can start refactoring and breaking out smaller contexts, re-run the tests and make sure everything passes.

But how does that help us iterate faster? It helps because I no longer have to worry that some day we’ll figure out a better way to do this. In fact, I’m almost positive we will find a better way. So rather than worrying about doing things the absolutely best way right now for all eternity, I just have to worry about doing things the best way for the problem at hand. As soon as I realize the data context is too big, it’s time to refactor.

I believe the ability to iterate fast is what’s going to help us not wind up in the “that code is horrible” trap.

Pluralsight Results

Yesterday I was sitting in a meeting. I pulled my phone out to see what time it was, and I saw I had an email. As I pulled down the notification drawer, I noticed it was from Spencer, my contact at Pluralsight. As I opened the email, I wasn’t nervous. I knew I had done my best. I had put close to 30 hours into my first submission, and easily another 10-20 on my second submission. All told, I spent around 40 hours to make 20 minutes of video. I didn’t just slap together a video. When my first video received the review of “We’d like to see another video,” I tried my best to take their criticism and apply it.

So as the email open, and the first word I saw was “Congratulations” I was pretty excited.

I have been accepted to be a Pluralsight Author. It’s something that even 6 months ago, I never imagined was a possibility. But thanks to some very kind conference attendees, other speakers, and friends, I’m there now. It all started when a man named Darin emailed me after my last time talking (KCDC14) and suggested I try to become one. Cory House, who I’ve met and talked to at a couple conferences, is a Pluralsight author and he was more than helpful in reviewing my videos and providing good feedback. Coworkers and friends also watched my videos. They provided actual feedback and didn’t just say “Looks good to me!”

So tonight, I electronically signed my agreements with Pluralsight. I’ve also submitted 3 possible class topics. I know there is some review/vetting process for the courses, so I don’t know if they’ll select any of these 3, or which one. I also don’t know exactly how long this part of the process will take. But hopefully in a few months I’ll be able to write a blog post telling you to go watch my Pluralsight course.