About 8 years ago, I started the biggest journey of my life: Having kids. Before my wife and I had our first child, to say I was anxious is an understatement. Of course I was happy too, but a lot of the time my thoughts would clash between things like “Will she be healthy and have two arms and legs?” and “How will I function with no sleep!?”. It was a constant tug of war between selfless and selfish thoughts, causing spirals of anxiety for me.
As a software geek, I kept thinking about the amazing article Jeff Atwood wrote called “On Parenthood” where he presents one of the best data visualizations I’ve ever seen related to the raising of children.
After our daughter arrived and we spent our maternity/paternity leave groggy and caring for a beautiful new infant, we settled into the rhythm of having a newborn. We got used to losing sleep and started making sacrifices for ourselves for this new bundle of joy. We did this without a second thought. It just happens, and when you’re in it, you’re in it. Looking back on it, the anticipation of having a newborn was actually much worse than having a newborn!
But, after a few months, something happened that I didn’t expect. Everything else got easier.
Drama with friends? Whatever, I don’t have time for that, I’ve got a baby to take care of! Drama at work? Ergh, I’ll keep my head above the fray – I need to focus on work so I can get home and take care of the baby! Should I use NoSQL or relational databases at work?
It’s that last one I want to talk about a little more. This is the type of decision I would pontificate endlessly over. I’m a consensus-seeker too, so my own internal gnashing of teeth would be amplified by asking for others’ opinions.
But after my first was born, the answer to these types of questions came a lot more quickly. In the case of SQL vs NoSQL, for instance: “Well, this seems like a wash, so I’ll just pick the one I’m familiar with and get the job done, so I can spend more time with my family.”
This decision-making process could sound like a bad thing – Like i’m cutting corners because I want to spend time with my family. Honorable on a personal level, but negligent professionally. Maybe, but I know that I would never be negligent about making a decision, it’s just not in my nature. But knowing that a beautiful living being was waiting for me at home really forced me to (subconsciously) make a decision a lot quicker.
It got even more crisp when my son was born four years later!
With some hindsight: This type of pressure is the best thing that has happened to me both personally and professionally.
It has forced me to become a much more crisp and quick decision-maker. It forces me to prioritize getting things done over making things perfect. It has also made me more scrupulous about when attention to detail and striving for perfection is important, and when it’s not. And finally, it has forced me to become well versed in Essentialism and the subtle art of saying “No” to things. It’s amazing how much better your life becomes when you become comfortable with saying no.
As a Software Development manager, all of this also has positive effects for my teams as well – I’m much more comfortable delegating decisions to them. Being judicious with my time forces me to let those who are closest to the problem at hand make the decisions. Of course, I always want to be informed, but I make it clear that my input shouldn’t hold them up.
I have found that often in the world of software, shipped is better than perfect. Feedback from users is better than spending time and money making something that may not be used by anyone. My kids helped me realize that and I thank them for it.
Years of toiling away with Java Virtual Machine (JVM) technologies made me realize that the only thing that really matters when developing in the JVM space is that you can intelligently talk about it. These complex projects rarely get deployed to production or used by users, so it’s usually sufficient to just have a headline and be able to talk circles around your businesspeople to confuse them. Then, you can go have a beer.
Written in state of the art Kotlin using complex AI (if/else blocks and switch statements) it is truly a groundbreaking piece of technology.
Please send me copious amounts of money so I can buy a beach house and retire. Thanks!
… And my job is to develop software. I have an IT-related degree, but not in Computer Science. I used to feel ashamed of this. But losing some brown hair and gaining some grey hair (and losing a lot of hair in general) has taught me that a CS degree doesn’t make you a good developer.
Some of the most brilliant software engineers I have worked with in my career have been art, history or philosophy majors. And with some hindsight, this makes total sense – Software and coding is mostly art and part science.
I’ve been known to get on a soapbox and tell others that I believe the majority of software developers today are digital plumbers. And I mean this as a great compliment. Real plumbers are talented, smart people who do very important work in our society. They also get paid handsomely for it, much like software developers.
The majority of modern web applications and mobile applications require using pre-existing frameworks and libraries that do a lot of advanced mathematical heavy lifting for you. If we go back to the plumber analogy: Guess what don’t plumbers don’t do? Make pipes. Qualified engineering firms do that. Plumbers are doing the work of installing pipes in people’s homes so they can have clean water. This is very important work.
As software developers, our frameworks and libraries are our pipes, and we are the plumbers making things happen for real people in real life. We all should be proud of this.
I am a firm believer that the majority of tech related work does not require advanced science or engineering degrees. Much like being a plumber doesn’t require a college degree, it requires a lot of hands on work and training.
In software, if you know the basics, you can be a wildly successful developer. My definition of “the basics” is the following:
Data Structures (Lists, Linked Lists, Sets, Graphs, etc)
Algorithms (including some basic Big-O analysis)
Working knowledge of databases: Basic SQL and general knowledge of different database types and how to interact with them)
Some object-oriented programming
Some functional programming
Working knowledge of the Linux (*nix in general) command line
Working knowledge of a source control system (I default to Git here nowadays)
Working knowledge of a scripting language (can’t go wrong with Bash)
You might have to start low on the ladder, but if you know these things you have the tools to work your way up.
If you want to work for a technology pipe-maker (e.g. working on new Machine Learning algorithms or other advanced tech), then yes – you need a Computer Science degree. And more power to you, my friend. Those people are extremely valuable in a different way. Plumbers can’t plumb without pipes, right?!
In most software developer jobs, perseverance, attitude and passion for the job are far more important than advanced CS skills. So is your desire to be part of a team and help others. So is your desire to build things of quality.
Possibly most important is your creativity and ability to break the mold of existing thought processes to simplify and make things easier.
I also believe that requiring these degrees when hiring is a form of bias. There are many qualified engineers out there with diverse backgrounds all tech hiring managers should be considering.
Related to this topic, please check out No CS Degree – This site contains a lot of interviews with people who have No CS Degree and share their story. It’s inspiring.
If you made it this far, thanks for reading, and I thought I would also take the opportunity to share my own story with having No CS Degree and the impostor syndrome I had for years:
After taking a few introductory Computer Science courses freshman year in college, I switched majors. I was not interested in learning how to solve math problems with C++ (this was 2001…). I went on to graduate with an IT degree, and really enjoyed my courses and learned quite a bit. The courses were much more practical and focused in terms of delivering results for businesses. In that degree program, I even took a few more programming courses. But I didn’t get the theoretical computer science and math background that many developers have.
For a long, long time I was ashamed of this fact. Out of college, my first couple of jobs involved gathering requirements for applications and also acting in “project manager-y” type roles (I wasn’t experienced enough to really be a project manager). I fell into coding when I got the chance to work on a team developing a small application. And I found that the handful of programming courses taught me more than enough coding to do well. And years later, I’m so happy I fell into it and am enjoying the confidence that comes with being older and wiser.
I have never worked on applications that require lighting fast searching of millions of web pages, or heavy mathematical lifting. I write web applications for modest amounts of users and the backends that support them. But even though those applications might not be Facebook or Google, they are important, and the systems are complex because of the amount of integrations with other systems they have. Keeping those complex systems as simple as possible (as well as the code within them), is a huge challenge in and of itself with a combination of communication and technical challenges. It’s the art, rather than the science of it, that appeals to me.
In college, I would always take advantage of my Professor’s office hours whenever I could. They made themselves available regularly, and gave extra help. Many times with a smile on their face because someone was actually coming to office hours. Why wouldn’t I take advantage of them? I never understood people why many people didn’t.
Something I learned by semi-regularly attending my professors’ office hours is that I would develop a rapport with them which paid off in additional help, tips and just general goodwill towards me. Was this brown nosing? I guess it could be construed as that, but I wasn’t after better grades. Most times I was genuinely struggling to grasp a concept from class and needed help. I was never the type of student to accept “good enough” or “I get most of it.” I always wanted to get everything. As a side benefit to office hour attendance, I developed good relationships with professors which ended up giving me other opportunities outside of class.
I’ve spent the last couple of years working on client projects at a software agency. The same approach of going the extra mile to ask a client, or peer, or your manager for their opinion on something, or to communicate a little bit extra with them not only benefits them, but benefits you in the future by building up a Goodwill Budget.
I always liked the concept of a Performance Budget when building web apps. I think that this idea can apply with your relationships in business (and really anywhere in life). When you take the time to listen to people, do small, but meaningful extra things for them, and just generally care about the quality of your interactions with them and what you deliver to them, you build up your goodwill budget with that person.
What could you spend your Goodwill Budget on? One example is that you can use it to stand firm on a point you believe strongly in where the other person disagrees. For example, maybe you don’t think that a feature should make it into the next release, but the the other person does. How much of a Goodwill Budget do you have with that person? If you have lots of goodwill points in the bank, the chances are higher that if you argue your point articulately, that they will see your point of view better and end up taking your side. If your budget is low, the other person’s tolerance for your arguments will be much lower.
This also applies to the inevitable mistakes we make as humans. Others are a lot more likely to forgive small mistakes if you have a lot of goodwill to spend.
Just like any budget, you have to plan to save up before you can spend. So, if you just met someone, you can’t spend down your budget because you don’t have any. It takes some time, kind actions and quality delivery to build up your budget.
As I write this, I’m realizing how something like this could be twisted into some kind of nasty manipulation tool. It shouldn’t be. Think of this like some kind of bizarre variant of the golden rule – If others treat you with kindness, communicated well and deliver things of quality to you, won’t you be happy? Won’t you be more apt to give them grace when a mistake is made or they disagree with you?
An engineering team that is gelling together is a wonderful thing. There is nothing like watching teams of smart people work together to solve really hard problems. They’re so good at it they make it … fun! This only happens when they’re motivated, empowered to do what they feel is right, and not afraid to push back when they feel they’re not doing the right thing.
Getting there is hard. The usual engineering management guidance is usually about hiring the best people – A players don’t do well with C players, etc, etc.
Well, of course. Who doesn’t try to hire the best people? But, it’s really freaking hard to get right! There’s gotta be more to it…
Spotify was nice enough to share their engineering culture strategy in a couple of videos on their engineering blog a few years back.
Their practical approach, based on learning from things that didn’t work, is a breath of fresh air compared to most software management in organizations I’ve seen. I loved their strategy because it focuses on people first as opposed to metrics and engineering rigor. Of course those things are important, but culture is far more important. Everyone does better when they feel comfortable and empowered.
I’ve rewatched these videos many times, and recently took the time to take some notes on the second part that I thought I would share. If you’re intrigued by a particular note, you can go to that portion of the video to learn more. Though, if you have the time definitely watch both videos all the way through.
There is also a Part 1, which is great, but Part 2 has a good overview of it at the beginning, if you’re short on time.
During my first few years working in software, I had the opportunity to work with a mentor who had the best approach to introducing new ideas that I’ve seen. The best way I can sum up the approach would be “Show, don’t tell. And don’t be a jerk.”
To give some more context, we worked in an organization where change was widely viewed as something to be feared, rather than something to be embraced. Ideas for change were often met with resistance, especially by management.
The primary way that he worked his magic was through small experiments – with the bulk of the work done on his own time. If there was something that he viewed needed to be changed, he would take a small slice of that problem, and apply the new idea to it. It might not solve the whole problem, but it showed the path toward it. For example, if we had a problem with triaging production issues from messy logs, he might take a crack at changing the styling of alert emails that got sent out to be cleaner (this was before Splunk and other tools). But not everywhere, maybe just in one place on just one of our many applications.
Then, he’d show it to the team to see what they thought. He did this without explicitly selling the idea – just stating the facts and showing off a working example. Seeing the idea actually working, the team would often embrace it. We also had a working template to start from, should we decide to pursue it. This was a seed that he planted, and if the team decided to nurture it, that idea would grow a life of it’s own with just a little bit of initial effort.
What didn’t happen? Talking about the idea for change before starting. You didn’t hear “I think we need to change X to Y because…” followed by an hour of debate.
I’m guilty of doing this, and it doesn’t work. Talking about an idea for significant change, without action, dooms it from the start. Imaginations run wild and what-if scenarios scurry about like frightened mice. All the time wasted pontificating could be spent doing a small experiment to see if the idea really works.
If you do a change experiment simply, and test it cheaply, chances are you have a lot less to lose than a meeting where the whole team talks for an hour. Paradoxically: if the idea is complex and hard to start on, sometims the best, cheapest experiment to run is a thought experiment and asking people what they think. You have to use good judgement, but avoid the dangers of the hour long debate!
We also can’t forget that people sometimes are apprehensive of change in a team. They’re comfortable working the way they already work. Why would they change? But if you have visible progress on that something works, instead of just words, it’s hard to be afraid of or argue with. Also, don’t forget to hear them out. Why are they resistant? Simply letting people talk through their feelings goes a long way to helping both you and them understand the new idea. They may have very good reasons for feeling as they do.
You have to be prepared for this strategy to fail. You will have ideas that are great and your team just isn’t ready for. Or, you will have terrible ideas that are rejected for good reasons. You cannot get defensive if these experiments do not pan out. You cannot under any circumstances get upset if those ideas are not embraced immediately. If they aren’t, try again, softly, with a slightly different experiment.
Many of us in software work with Agile processes, quickly iterating over software features until we hit on what our users want. Think of changing an organization the same way. If it doesn’t work the first time, what can you do better? Was it a problem with your idea, or was it just not communicated successfully? Was your example too small, so that it didn’t really present the power of your idea?
Above all: Don’t be a jerk. Lasting change on a team requires buyin, and that doesn’t happen if you’re not empathetic.
So go out there, do good work and plant some seeds for change in your team.
Shortly after, I came across “Why I Struggle With Node” by Graham Cox. It’s a great post about why he loves Node.js, but gets frustrated with its ecosystem and prefers that of Java.
The post made me think of my conversation with my friend. I linked to Graham’s post as a starting point, added some additional thoughts and sent them to my friend to give him a place to start with Node again. After I wrote it up, I thought it might be useful to other Java developers who haven’t taken the dive into Node.js and would like to, but might be intimidated or not know where to start.
If you’re in that boat, I suggest you first read Graham’s post. It has a great list of tools to start with that translate well into front end code too.
After you read that post, here are my notes and addons that I think might be helpful if you are coming into Node development from Java in the beginning of 2017:
Also, before you dive into creating a full app or start setting up tools, learn the Promise API and use it from the start in your code. It will make your code easier to reason about, and will make your life much more pleasant once you get past the initial learning curve. If you can, use the Bluebird library for Promises. It has lots of great extras on top of the native implementation, and rumor has it that it’s even faster.
Like Graham, I use Grunt for building, too. I haven’t tried Gulp, I’m sure it’s great, but I’ve used Grunt for a while and have found it effective. Though, like Graham, I do miss the fact that Maven takes care of a lot of the gruntwork (ha ha!) for you. For my team’s apps, we have separate Grunt tasks and configurations for building front end and back end code since folder structures are different.
This is mentioned in the post but I thought I’d provide what I’ve used: Istanbul through Grunt. It’s nice and simple and does the job well.
Graham mentions that Node logging isn’t as nice as what he’s used to in Java. That’s true, but I’ve used Winston quite effectively in production apps.
Graham is right, debugging in Node is hard. I attribute some of that to it’s asynchronous nature, though.
I’ve used node-debug effectively as a debugger. It’s quite nice, but a real pain to setup. But, if I’m being honest again, usually I try to use Winston (mentioned above) to put some nice low-level logging statements in place so I can debug with those, then turn logging levels up and down as needed. Sometimes those low level statements help when you’d least expect it.
When I first started with Node, we were using a dependency injection framework in Node since my team was used to using Spring in Java. After a while, we just got frustrated with it and abandoned it.
Graham’s comments about integration testing being much easier in Java are spot on. I haven’t come across nearly as many drop in, in-memory replacements for connected systems like databases or message queues. This makes it tough to integration test. What I’ve done in the past is to create throwaway Continuous Integration database instances at the beginning of the tests and then clear them out at the end of the tests. It’s not that bad once you set it up once, but I yearn for the ease of using something like HSQL in Java.
Team Development Environments and Docker
My team has half Windows users and half Mac users. It makes for a challenging environment for everyone to setup their development environment in Node.
If you’re on a team with developers using multiple platforms, and deploy to Linux, what I recommend is to create a Dockerfile which defines your development environment. Then, use a Docker volume mount to put your source code inside the container. (Side note: Use an official Node.js Docker image as your base image). This lets you use normal Docker build/run commands to bootstrap your dev environment. The volume mount lets you dynamically update your code so you can still iterate fast, as if you were working on your local machine. It works well across platforms (no worrying about exceptions in Windows), and as a bonus, if you ever want to run your app in a Docker container, you’ve already got it more than halfway there. I’m hoping to post more about this in the future.
I’ve been developing in Node for about 3 years now, and I still really love the developer experience. Sure, I’m probably not using the latest and greatest tools that just came out, but this workflow has gotten me to a good place where I can be very productive and crank out some good quality code.
I hope some of these notes help you do the same.
What tools/techniques/libraries did I miss that were important for you when you came to Node from Java?
As a coder, it can be easy to get mired in details. Our job is to manage the details of a business in code. And with the best of intentions, we may even create more details for ourselves through our designs and technology choices.
Worrying about so many little things, it’s easy to lose sight of why we’re putting fingers to the keyboard in the first place. Asking a simple question: “Why?” can help you rise above all the details to see the forest through the trees and make better software.
When assigned a task or project, many times my first reaction is to think of which technology is most appropriate to complete the task, and then quickly after that, start formulating how I would code it.
The technology is the fun part! And it’s our job, right? Well, yes and yes, but immediately jumping into a technical solution is a guaranteed way to make things more complex than they need to be.
And while you’re making things more complex for you and your team, you might be hurting your customers by not delivering what they really need or want.
Next time you get a project, instead of opening up an editor, or Googling, or drawing a diagram, first ask “Why am I solving this problem?”
If you don’t know why, ask the person who gave you the task. If they don’t give you a satisfactory answer: ask more questions. If they still can’t answer your question, and you can feasibly do so without getting fired, ask them who else can tell you why.
“My boss told me to.” is never an acceptable answer on your part or anyone else’s.
What is a good answer? I don’t know, stop asking questions! Just kidding. But, it should probably address one or more of the following:
A specific use case. For example: C-Level executives need this new report to make decisions about budget next year. Or: All users need to be able to save their login credentials in a cookie so they can save time each time they access the app.
Ease of operations. For example: Formatting log messages in XYZ format will allow the application support team to parse them easier and identify causes of bugs in logs quicker and make our customers happier.
Speed or quality of changes. For example: Writing an automated acceptance test suite will help us react better to customer needs by getting features out faster.
But ultimately, a good answer to “Why?” is one that makes sense to you and isn’t simply “It’s my job to write code” or “My boss asked me to.”
It is staggering how a simple “Why?” can halt people in their tracks and cause them to change their decisions, often for the better.
Especially on a team of seasoned people who have been with an organization for a long time, it’s good for someone to keep asking “Why?”. Chances are, there’s a bunch of people in the room with differing opinions, and the question will get them out in the open. Sometimes, it might even turn out that the task shouldn’t be done at all. Which is good, that frees you up focus on more important things. At the very least, you’ll probably dig up some serious “gotchas” about your task in the process.
Your Leaders Are Human
When you’re looking for answers, be patient and remember that the product owner/architect/supervisor/bossman/leader you’re asking is busy and he is human, just like you. He has lots of stuff he needs to get done, and sometimes he make mistakes and has lapses of judgement. Your job is to consult with him to get things done for a business. You can’t consult with him if you don’t fully understand why you’ve been assigned work.
If you don’t understand why, or he didn’t explain: Consider it part of your job to ask more questions. If he is at all a decent leader, he will take the time to explain the value of the bug you’re fixing or the enhancement you’re doing.
If your leader’s answer ends up being “because my boss told me to” and you can’t get any further then, well, it might be time to find a new organization. Unless, of course, you’re up for the task of managing upward, which is probably a good topic for another post!
Reducing Accidental Complexity
Earlier, I mentioned that we sometimes create unintended details through our everyday choices of technology and design. These unintended details are generally referred to as accidental complexity. This is opposed to essential complexity, which is solving the “real problem.”
Accidental complexity is part of our job and we can’t avoid it. But we can mitigate how much of it we create! Asking “Why?” helps.
When you ask why you’re doing something, the answer of “Because technology X needs technology Y” should be an immediate red flag that someone doesn’t fully understand the business problem at hand.
Writing code to solve a problem that other code created, or to solve a shortcoming of the AnguReactBerJS framework is not providing any value to the customers of your software. You are probably just creating more accidental complexity instead of solving a real business problem.
Asking “Why?” will help you focus on the simplest way to solve a real business problem instead of simply fixing technology. You might be able to bring your solution up a level to eliminate a technical issue or shortcoming altogether.
Say you’re given the task to add a set of Automated Acceptance tests for your application. Do you know why you’ve been given that task?
Is it because we want to use SeleneCucumBybara, the latest, greatest testing framework? Probably not. Is it because we want to shield ourselves from creating bugs and allow us to be more flexible with the codebase so we can get features out quicker? Now you’re probably on to something.
Knowing “Why?” will help guide you through the immense pile of decisions you’re going to make when you start writing code. You’re probably going to make multiple decisions per line of code you write. You want your coding decisions to be made with the right values in mind. For instance, if you want to safeguard against a changing codebase, knowing this might help you target tests for the area of code which changes the most.
Knowing Where To Cut Corners
“Cutting Corners” is a phrase engineers hate, myself included. But in the reality of most business software development, a shipped product is better than a perfect product, so there’s going to be some paint dripped on the floor.
Asking “Why?” will help you know where it makes sense to spend less time polishing code and where a cut corner is acceptable.
For instance, if the answer to “Why?” is “We need to get this feature out fast so we have first mover advantage” (meaning time to market is important), maybe it’s more important to have a few solid end to end automated acceptance tests than it is to have good unit test coverage.
Or, if the answer is “This bug is causing customers to be charged $5 per order by mistake”, you probably want to spend more time writing tests for your code and less time polishing the front end.
Remember that the concepts of Technical Debt and Backlogs (in Agile) exist to help us make sense out of the imperfections we might create. These are ways for you to quantify your technical risk, track it, and hopefully address it later.
Does a problem happen often? Ask “Why?”. This will help you figure out if a problem is systemic. Fixing the cause of a systemic issue will save the team repeated effort which will allow everyone to focus on solving problems with more value.
If you’re new to software development, it might seem intimidating to ask such a simple question all the time. You might be afraid of seeming like you’re not good enough. But newbies are in a perfect spot to ask “Why?” A good team should have an understanding that a person new to software won’t know it all and needs some help. They should also come to realize that questions like these will help the whole team get a better understanding of what they’re doing and if it needs to change.
I think it can be harder for someone who has a lot of experience to ask a simple question like “Why?” all the time. With more years of experience come greater expectations on the part of others. This makes it more likely for a seasoned developer to perceive themselves, or possibly even be perceived, as being incompetent, even though they are anything but.
Regardless of your experience, it takes some courage to ask “Why?” Just keep on asking and feel dignified knowing that you’ll find better answers and do better work than those who don’t.
In one of the talks I attended, Jeremy Keith reminded us that though the web has become a complicated beast, it is still amazing in its simplest form. And we shouldn’t forget that.
This sentiment rang very true to me – It made me recall the pure excitement I felt back in the mid-1990’s, when I was 13 years old, putting my first web pages on the Internet. A kid like me could create something from nothing, and better yet, self-publish it and have it accessible by the whole world. Anyone could see my content!
Along this path, I forgot about the power of a browser rendering simple HTML and CSS. And perhaps more importantly, having that content be globally accessible in one simple place – a URL.
These ideas of were underscored by almost every other speaker at An Event Apart. They reminded us that in order to create the most useful web sites for a user, we need to forget about fancy layouts and CSS. Instead we should focus on content first and ask ourselves: “What is most important for the user?” We should make that content simple and easy to find, regardless of how advanced their device or web browser is. Then, get it captured in plain, semantically meaningful HTML markup. The rest will fall into place.
I write this with the hope that it will help me remember these ideas for the next web app I build.