17 ms·
What Makes a Great Software Engineer? Just My Thoughts
- thallukrish 10y agoNice, you drove home the point of simplicity in building software which largely occurs over time in the hands of a good software engineer. Do more with less code. Coincidentally, I had similar views in this piece some time back.. https://medium.com/@thallukrish/on-coding-e3c03771a369#.bb5kuf6zq https://medium.com/@thallukrish/on-coding-e3c03771a369#.bb5k...
- elliotchance 10y agoCheers, great article. Left my own comment ;)
- andrewstuart 10y agoI wrote on characteristics of a great software developer a while back. http://www.supercoders.com.au/blog/50characteristicsofagreatsoftwaredeveloper.shtml http://www.supercoders.com.au/blog/50characteristicsofagreat... The problem is that people try to recruit for these things. When recruiting, follows Joel's advice - smart and gets stuff done.
- biocomputation 10y agoI think your list is fantastic!
- bastijn 10y agoProbably the first time a see a list of 50 points in which I wouldn't object to any of them. Impressive.
- lopatin 10y agoHow did you finish the list? I'm still processing the last two items.
- billforsternz 10y agoReally impressive work. You've taken "smart and gets things done" to the next level.
- elliotchance 10y agoThat is a fantastically comprehensive list - I was racking my brain for a while to try and think of something before I replied. Not sure if this one is covered already but maybe... Student; is able to ask for help. A lot of these are hard to objectively test for (in a recruiting sense) because they can be subjective or be dependant on the working environment itself. It never hurts to have more information that less, though!
- agumonkey 10y agoThis list is depressingly long.
- lwhsiao 10y agoGreat write up. One of the challenges is definitely finding a system that recruiters can use to prioritize these things.
- elliotchance 10y agoI'm generally not a fan of recruiters simply because the vast majority of them are sales people first, and tech people second (or often no technical experience at all). Compounded by the fact some people interview very badly but are good engineers and visa-vera. Even if you have experienced engineers doing the screening process (separate from the company being applied for) I still think it would be challenging because theres no "correct" way for a team to work and companies are so vastly different. It definitely is something to think about. If you do some up with something, let me know :)
- seanwilson 10y agoGreat list. One I would add would be understanding what the client's problem and building an appropriate solution. Too many times I've seen developers just dive in coding up the solution the client suggested without trying to understand the problem the client is trying to solve. For example, by adapting the problem to using an existing CMS or SAAS you can avoid a huge amount of custom coding. A good developer would be able to write simple code for a given solution but a better developer would suggest a simpler solution leading to even simpler code.
- Joeri 10y agoThis is exactly the thing that makes a person a "10x" developer. Being able to write lots of reliable code in a short amount of time is a good trait, but knowing when not to write code is equally important.
- elliotchance 10y agoFor me this falls in to the "understanding" category. The problem your trying to solve and what the client wants are often mixed up as the same thing - but they seldom are. You shouldn't expect that the client will know what they want even if they ask for it. There is however always an underlying reason why they think they need it. Take the time to understand that rather than just more billable hours. It will be better for you and them in the long run.
- BerislavLopac 10y agoIn my experience, laziness is one of the most important traits of a good developer.
- hoodoof 10y agoTo be truly lazy you must get it right the first time, and write the minimum possible code.
- MaulingMonkey 10y agoYou need the right kind of long term laziness - but yes.
- SlySherZ 10y agoYou have to be careful how you define 'lazy' in this case. Suppose a developer just quickly writes code that fixes the current problem, but doesn't care about the consequences long term, or doesn't fix the underlying problem - not good. Now, if you define 'lazy' as someone who will go to great lenghts to not do boring tasks in the future, yes, I completly agree :)
- elliotchance 10y agoSpot on in my opinion ;)
- dmolony 10y agoYou probably want to the right thing
- elliotchance 10y agoThanks, I've fix it up.
- adrianggg 10y agoGreat article. I think you have hit on something here that only comes with a lot of experience and looking back and what really worked. I rarely see an article that I think YES. TOTALLY. Well done!
- elliotchance 10y agoThank you for the kind words :)
- meeper16 10y agoBeing able to step outside software engineering when engineering software.
- jomamaxx 10y agoYeah! This. 'Perspective' ... Mini perspective: step away from the desk, do something literally creative. I play my guitar. Major perspective: get the hell out of the city, actually do something on a weekend. Come back - all of a sudden you have fresh eyes and see things more clearly. I actually think that soft devs should take more vacation. You know that professional concert musicians only practice a few hours a day - any more is pointless. You just can't concentrate that long. A really gutsy move would be for Google to give a bunch of 'long weekends' where nobody can work, or even more vacation. And see what the results are.
- elliotchance 10y agoFresh eyes on the problem is always good, usually after lunch or you have slept on it. I find when my brain starts to grind to a halt I just go an do another un-related task to force myself to completely forget about the original task. It does help because when I go back to the original task my brain has to context-switch back into it and in doing so it may look at the problem a different way. Extra holidays would be great! However, I think more holidays would make some engineers more productive and some less productive... I'm not sure if Google is still doing their 20% time, and if they are I know it doesn't apply to all the FTE engineers.
- kator 10y agoI've heard people say laziness is important. However that is a misnomer, the reality is the best inventors and engineers are sort of long-term lazy. They will spend 40 hours building something to automate a thing you can do in 15 minutes. But, they know that they or others will push that button so many times the 40 hours will come back quickly over time. An example of this is a strong senior engineer might take a lot of time laying the foundations of a project, the scaffolding needed to really make coding a breeze and enjoyable in the future. This is because they're lazy, they want the future to be easier so they invest today to make the future just a little bit easier.
- Dolores12 10y ago>They will spend 40 hours building something to automate a thing you can do in 15 minutes. That's because building something new is exiting and interesting, while doing something boring for 15 minutes is ... boring?
- bluejekyll 10y agoThe point is more that by saving those 15 minutes, it's a cumulative saving for all future use cases. Though, I don't think I fully agree with this in all cases. It can be hard to predict when something really is going to be used often enough that this is important. IMO you build the minimal thing that does the job, then after understanding the use case go back and refactor to deal with the accumulation of 15 minute pain. Doing it right at the beginning is the definition of premature optimization. And on the topic of building new, this is a mistake many developers make: that it's easier to build new, then to refactor existing. What they fail to realize is that the old code they think is too difficult to maintain is battle tested, in production, has operational understanding associated with it. All software goes through this cycle, and so while it's fun to build something new, you are inviting debt while doing so b/c of the unknown production issues and edge cases that need to be figure out after it goes live. It's not always wrong to rewrite, but IMO, it's a last resort. BTW, this is why SOA is important: strong defined contracts/APIs between services allow for components to be replaced with a higher degree of confidence.
- MaulingMonkey 10y ago
- highCs 10y agoGood post. I think too that reducing code is key. Here is how I like to show it. Let's see what impact "size of code" has on "time it takes to add a feature". Just consider a graph where the X axis is "size of code" and the Y axis is "time it takes to add a feature". Obviously, the function is increasing, and probably faster than linearly. Let's see what impact "size of code" has on "number of bugs". Same thing. Let's see what impact "size of code" has on "time it takes to find a bug". Same thing. Let's see what impact "size of code" has on "time it takes to resolve a bug". Same thing. Let's see what impact "size of code" has on "time it takes to refactor a piece of code". Same thing. Let's see what impact "size of code" has on "time it takes to a newcomer to be productive on that codebase". Same thing. And on and on and on. There is two canonical points on those functions. The first canonical point is when the codebase is too big for the value it brings. When you are here, you are in deep trouble. Basically, the cost of doing anything in that codebase is too high in comparison of the value it brings. A sign you are here is when you spend more time in meetings discussing what to do, than time coding. The second canonical point is when the codebase is notably small for the value it brings. When you are here, the project looks like magical. The programmers look like 10x programmers. Indeed, doing anything on the codebase costs surprisingly little in comparison of the value it brings. A sign you are here is when you are not asked for estimations.
- elliotchance 10y agoYou should totally turn this into a xkcd-like comic ;)
- progman 10y ago> 1. Simplicity Reduces Code I always follow the KISS principle, if possible. It makes maintainability so much easier, not only in Software but also in Hardware. Every additional layer of complexity adds to the probability of failure.
- hliyan 10y agoFewer lines of code don't always mean simpler code. Sometimes it means cleverer code (read: harder to understand and maintain). Three quotes I frequently repeat in this context: 1. Duplication is better than the wrong abstraction 2. Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. 3. Code must be written for people to read, and only incidentally for machines to execute
- jomamaxx 10y agoYeah. This. I think that sometimes people that 'more compact code' is what we mean be 'less code' and it's really not. I think the differentiation is at the algorithmic level: it's not algorithm density, it's 'system clarity' that's key. I find a nice rule of thumb is 'don't code two steps ahead'. Just because you may think you need to write a couple of 'duplicate lines' here and there, don't even bother abstracting for it. Wait until there's a few more. Software people tend to outsmart themselves and build way ahead of what they need. I think it's better to 'discover' the minutia of architecture than to plan, it all but the grandest elements. An artists drawing a figure will 'sketch out the form' - that's the basic architecture you can do up front, but it lacks detail. The 'art' comes out incrementally piece by piece. And the human aspect: it should hopefully read like English to a casual observer. It also helps to think of it from a business perspective: + What the code does is an economic asset + But actual lines of code are a cost centre and an ongoing liability.
- JamesBarney 10y agoYeah when I find duplicated code I always ask myself is this duplicated because this is representing the same domain concept in two different places? Or is it duplicated by coincidence? I'm much more aggressive about refactoring the former than the latter. When I was first starting off it was always hard for me to tell the difference so I abstracted a lot of things that I shouldn't have, and you could tell from the terrible method names that follow leaky abstractions.
- elliotchance 10y agoOne of my biggest pet peeves is code duplication from lazy copy/pasting. I find it's a good exercise for myself to sometimes pretend like the copy/paste key are not available to me. I had to think about the first one for a moment, but I do agree. It's better to abstract later with greater knowledge than the much more difficult task of trying to debug or fix it later. It's an outstanding list and great rules to work by!
- phyalow 10y agoAutism.
- segmondy 10y agoWhat do you most developers hate? Legacy systems! Why? so difficult to change, poor documentation, no tests, etc. A great software engineer, goes for simplicity but not in terms of laziness. 1. They keep the system simple enough and decoupled in the right way so that it's easy to change! 2. They have tests, not just unit tests, unit, functional, integration. 3. They document everything, code docs, design docs, design decisions docs, data structures docs, how to build, how to debug, how to maintain and change, etc 4. They do the really difficult stuff, they don't write the software for themselves, the develop for humans, customers. It's not about what you like, it's about what your customers like. This means having meeting and talking to others, getting feedbacks. 5. They keep learning, but they don't jump and adopt every fancy new technology, they stick to well proven stacks, so they tend to be boring.
- makecheck 10y agoThere should not be long strings of commits that focus on features. Continuous development means continuously looking after developers, too: intersperse commits that remove code, increase documentation, update versions of dependencies, fix ancient bugs or whatever else eases maintenance. Test suites should not just be thrown together, where every test is a "diff" of a giant log file! You do NOT want to be constantly fixing “tests” that “fail” due to trivial differences. Ensure that your code can completely expose all relevant state for one feature so that you can write precise checks and ignore any other output. There should be no compile-time options (like #ifdef) that are not automatically built before every commit. Developers change things, and they have to know exactly what can break by doing so (especially with languages like C++, where a tiny change can cause true chaos). Put another way, don’t set yourself up to discover problems weeks from now at the worst possible moment; build defensive code and infrastructure.
- mooreds 10y agoThe unspoken subtext is, of course, "as simple as possible while still adding business value". For example, there may be external constraints (contracts, regulations) that require more convoluted code. There may be certain business situations where there just has to be complexity. In these cases, we should strive to understand: * the complexity and the sources of it * how the complexity will change, and how much (as best we can, as predicting the future is hard) * what, if any, of that external complexity needs to be in the system we're building, and what can be pushed into human hands * how best to encapsulate that complexity so it doesn't spill over into parts of the system where it needn't be It's all well and good to say "keep it simple", but that can be difficult when there are external forces that are saying "the system must do X when Y, A when B, and C when D, except when X. Oh, and if Y then C, except when A", etc,etc.
- bitwize 10y agoIt's not just contracts and regulations. Example: Bob the sales manager doesn't want to view reports through your handy web portal. Bob wants them formatted in Excel sheets, zipped, and emailed to his corporate Exchange account daily. Bob is the only person in the whole company who doesn't like your portal, but he is powerful enough that his whims automatically become mission critical requirements. You either give Bob what he wants, messing up your clean design to implement functionality just for Bob, or you have failed to meet the business's needs and will lose the contract, end of story.
- paulftw 10y agoBefore you aim to become great by reducing your code please become competent in absolutely necessary basics: DRY, separation of concerns, basic patterns, security, etc.
- elliotchance 10y agoYes and no. I think we read these things in textbooks and either don't truly understand why they exist until we've made the mistakes or we go too far the other way and start dictating best practice on to everything. It's best to be be somewhere in between. It can only be learned by doing, not studying.
- hakunin 10y agoMy thoughts conveying similar message from a different angle: http://hakunin.com/cms-trap http://hakunin.com/cms-trap (for those who might've missed it when it got upvoted on HN 3 years ago).
- pklausler 10y agoGreat programmers write code that even bad programmers can understand. Bad programmers write code that only great programmers can understand.
- SlySherZ 10y agoSo.. if I understand my own code I'm a great programmer? :D
- elliotchance 10y agoThat's great, I'm totally using that: https://twitter.com/elliotchance/status/751926458658852864 https://twitter.com/elliotchance/status/751926458658852864. I couldn't find your twitter?
- andreygrehov 10y agoThere is a fine line between short code and readability, which is, by far, one of the most important factors of code quality. Say you have a code: $this->executeAfter(5); This is a short code, but it's not readable. What the hell is 5 here? Let's improve it a little bit. class Time { protected $seconds; private function __construct($seconds) { $this->seconds = $seconds; } public static function inSeconds($seconds) { return new self($seconds); } } $this->executeAfter(Time::inSeconds(5)); I've just added ~10 lines of code, but the readability of executeAfter is way better. In addition, the executeAfter method is more flexible, since it can manipulate the Time object now. This is a very basic example to illustrate what I meant when drawing a line between the short code and readability.
- segmondy 10y agoFor magic numbers, just use a well named variable, constant or configuration parameter. private const TIME_DELAY_SECONDS = 5; $this->executeAfter(TIME_DELAY_IN_SECONDS);
- gknoy 10y agoI'm a fan of named parameters, too: # python self.executeAfter(func=myCallback, delay_in_seconds=5) # or self.executeAfter(func=myCallback, after=delay(seconds=5))
- tdumitrescu 10y agoWhat this example is really lacking is a TimeFactoryFactoryAbstractSingleton to make it extra clear what that whole '5' thing is about.
- jamescostian 10y agoI believe you have missed the author's point - "Using more code is actually the lazy fix." The author would recommend something like: $this->executeAfter(5); // Execute after 5 seconds The above code is only 1 line, and is very clear. It does not add a brand new, unnecessary class, nor does it increase the surface area for bugs (adding a new class opens up the potential for new bugs, while adding a comment does not).
- mannykannot 10y ago"The best engineer will write zero code" - unfortunately, the author has forgotten to tell us what she does do.
- elliotchance 10y agoI'm a software engineer. If that's not clear from the article, you should be able to tell from the bio at the top and bottom of the page.
- mannykannot 10y agoI'm sorry, I may have been ambiguous. I was actually wondering what the best engineer does.