I did a take home software engineering test for a company recently, unfortunately I was really sick (have finally recovered) at the time 😢 I was also at the same time interviewing for an SRE position (as well as Software Engineering).
Got the results of my take-home today and whilst there was some good feedback, man the criticisms of my work were harsh. I’m strictly not allowed to share the work I did for this take-home test, and I really can only agree with the “no unit tests” piece of the feedback, I could have done better there, but I was time pressured, sick and ran out of steam. I was using a lot of libraires to do the work so in the end found it difficult to actually think about a proper set of “Unit Tests”. I did write one (in shell) but I guess it wasn’t seen?
The other points were on my report and future work. Not detailed enough I guess? Hmmm 🤔
Am I really this bad? Does my code suck? 🤔 Have I completely lost touch with software engineering? 🤦♂️
I’m also worried about the “lack of unit tests” feedback too, because I am reminded of TDD When did it all go wrong – Where you see so many engineers do “unit tests” wrong 🤦♂️ – If you don’t have time to watch this (rather long) video, TL;DR:
Unit tests test the behaviour of the system, or the API boundaries.
Unit tests should not test any implementation details.
They should let you refactor the implementation.
This was the original intent behind Unit Tests and AFAIK still is.
@prologic@twtxt.net Don’t let yourself get beaten down, man.
@mckinley@twtxt.net Yeah thanks man I appreciate it! 🤗 But right now I feel like my code sucks and I’ve been beaten 😢
@lyse@lyse.isobeef.org Thanks bud 🤗
@lyse@lyse.isobeef.org I found this article last night as I was trying to get to sleep (still not feeling 100%, sinuses still playing up 😢):
Best Practices for Testing in Go - FOSSA
Some good tips here in by a Jessica Black. I think I mostly agree with.
What do you think? 🤔 Got anything else to share along these lines? 🙏
@lyse@lyse.isobeef.org Yeah completely agree on good error handling and messages. I think I’ve personally done a poor job on this with yarnd
for example and probably ended up with logging and errors that were a bit too verbose and maybe too wrapped and redundant.
Speaking of good error handling. Have you or your mates/colleagues thought much about good/best practices around this? Besides the fact that it’s a bit of an “art form” – So is good Unit Testing really and even designing good interfaces.
For example, how much context to provide? Should you always wrap the underlying error? Is it always useful to bubble errors up the stack? I’m not even sure myself, but one thing that does come to mind is to avoid repeating the same error as they bubble up the stack. I don’t know how to define this clearly though in a set of examples and best practices like Jessica Black has done so eloquently in her article (yet)
We’ve barreled past the microblog line and flew straight over the e-mail chain line. This is just social blogging.
@mckinley@twtxt.net @lyse@lyse.isobeef.org Hahahah 😂 Honestly it doesn’t mayert too much 🤣 I always enjoy reading @lyse@lyse.isobeef.org’s thought like this 👌
@lyse@lyse.isobeef.org I think you probably need to drop the motion of error sub types as Go doesn’t have inheritance.
@lyse@lyse.isobeef.org I do like the idea of only logging one log line per incoming request especially for web service or APIs 👌
@lyse@lyse.isobeef.org I think the most interesting thing about errors.New()
is just how stupidly simple it really is:
// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.
func New(text string) error {
return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
That’s it! 😂
It makes me think that really we should just be defining our own error types all the time 🤔 Maybe…
@lyse@lyse.isobeef.org I think that’s spot on. Deliberate and careful design of errors is probably just as important as good interfaces 👌
With respect to logging.. oh man.. it really depends on the environment you are working in.. development? log everything! and use a jeager open trace for the super gnarly places. So you can see whats going on while building. But, for production? metrics are king. I don’t want to sift through thousands of lines but have a measure that can tell me the health of the service.
@xuu@txt.sour.is +1 on metric driven development (MDD?) Very important to have in a production system, service, whatever (codebase). I’m not going to look at your logs and try to decipher them, I want to see wtf happened at a specific point, then go hunt down logs around that specific time interval.
wow 😳 this has to be one of our longest yarns in a while 😳 @lyse@lyse.isobeef.org you might be interested in my observe package
@lyse@lyse.isobeef.org Speaking of which… I’m curious how you would have implemented this little demo:
Source: https://git.mills.io/prologic/gpt
You can tell I just “whacked” it together pretty quickly – mostly imperative, procedural style.