Thursday, 11 April 2019

When the interview they told you to expect is not the interview that you get

Alternate title:
"What's worse than whiteboard coding? Surprise quiz whiteboard coding!"

I had a bit of a shocker this morning. 

Was told that the interview would be about past work experiences, system design, cases where I've demonstrated leadership skills. So I spent quite a bit of time going through projects in the past, reviewing issues, what I've done, design decisions, solutions, etc.

What did I get instead?

Whiteboard coding. 

Absolutely no word about this from HR. Was this what they meant by "technical interview"? Do a tricksy for-loop and lets see if you can find out the secret. Oooh, hahah. I get it.

IMO, whiteboard coding is basically the 21st century equivalent of 1990s Microsoft interview questions like  "How would you move Mt Fuji?" 

 
And c'mon. Are we in high school now?
Surprise quiz! Prove you can code and deal with array indexes like a good boy.
Every. Goddamn. Time.

Now I didn't exactly set myself up for success, health wise. Mea culpa. Having only 5 hrs of sleep is not good. I was also throwing up this morning  from either stress or just phlegm in my lungs. Maybe I have pneumonia? Oh boy, I should be so lucky.

Second problem was about removing adjacent duplicate characters pairs from a string. I got stuck on this way more than I should have. I first thought of doing it recursively but stuck to iterative approach instead. Used char arrays when I could've just used ArrayList. I wasn't at my best, tbh. I screwed up my health and turned into a two-legged stress ball. It should not have been that awful for me. I should have been in the zone. (Yes, excuses, excuses.)

I don't need to tell you that I would've done this pretty quickly in a couple of minutes given a computer. Even using *vi*. 

So we didn't get to the third part of the interview, the one that would've discussed the things I actually prepared for, about System Design and work.

I suppose I could've turned the tables and said "Hey, why don't we first do the question I actually prepared for, then we can do this crap you've just sprung on me without any notice?" At least my effort from last night wouldn't have been a total waste. Get a quick win, then do the nasty thing I hate doing. I probably should've been more assertive. Maybe I would have felt more settled after that. Perhaps. Perhaps. Perhaps.

I was at one point tempted to just go and leave. As if that would change or prove anything. 

But what did I need to prove, really? I already did the online coding test the week before. What does adding whiteboard coding do? Does it raise the bar? How?

What are we trying to weed out at this stage of the process? People who hate being misled into preparing for something that was only 1/3 of the interview? The inferior, anxious types who don't like whiteboard coding? Programmers who are productive when using a computer? 😱


Wednesday, 1 March 2017

"I know.. instead of typing a forward-slash in a string, I'll declare a static variable for the "/" character"

Was looking at some code someone else wrote and came across:

public static final String SLASH = "/ ";     

FML. Dude. WTF were you even thinking? Why even have a constant? To save us from typing? Instead of one character you now have 5, and then the "+" symbol. What are the odds of making an error on a forward slash?  You're just using it in other static declarations anyway *in the same class*.



Friday, 3 February 2017

Java JPA and Generics and Type Erasure: Casting a List to List

Java Generics are a bundle of compromises and workarounds. Backwards compatibility is a PITA. We all know that. Anyway... 

I had a service class that, due to some refactoring, was now going to be returning a List<ParentClass> whereas before it could return a List<ChildClass>. We had some A/B testing inside the implementation, so in some cases, we would be actually returning a List<ChildClassTwo> from our DAO class.

My original fix for this was to create a new ArrayList and initialise it with the List of ChildClass or ChildClassTwo, but I didn't like the idea of having to create a new object just to change types.

But there's actually a better way, one that does not involve creating an extra wrapper object, that I found on StackOverflow.

To use the classic O-O hierarchy of  Animal and Dog classes:

List<Dog> dogsInLocation = dao.findDogs(location);

List <Animal> animalsInLocation  = (List<Animal>) (List) dogsInLocation;

So basically you are casting the List<Dog>  "up" to a List, and then casting it "down" to a List<Animal>

Trying to do 

 (List<Animal>)  dogsInLocation;

gives you an "Inconvertible types" error.  You can't directly go from a typed list of one type to a type of another. 

The workaround is to use type erasure, turn it into a standard List, which gets rid of the type information about List<Dogs>, and *then* cast it to a List<Animal>



Friday, 20 January 2017

Rebuilding Nexus - what we did wrong and how we fixed it


Nexus is just a searchable cache for all the various jars you either downloaded from the internet or generated from your code-base.

There are 2 main reasons you use a repository manager like Nexus or Artifactory:

* save on network requests, and make your builds faster
* predictability of builds, to serve as the 'source of truth' for all your release artifacts


Now we had a recent problem with Nexus. It got totally f*cked. I'm not privy to all the gory details, but we seem to have lost a few files.

This shouldn't be that big a deal, because we could just reconstruct Nexus from the files we already have in our Maven /.m2 directories -- we could take a new Nexus instance and populate it with the files we have. 

However, during the process we made a couple of errors, and it took us a few days as we discovered the problems day by day, depending on what projects we were rebuilding and what errors we were getting.

Now Nexus seems to have changed the way it works, and was no longer a system that could just be pointed to a file system to do a mass import. It looked like there wasn't actually any way to do bulk imports of an existing file system repository. So we had to do the import by individual files.

Most of the contents of Nexus were jars that came from either the main Maven repository, or other repos like Apache, Spring or Atlassian, so getting those wasn't an issue.

The main thing we had to repopulate were internal jars that we'd released and uploaded into Maven. One of the sysadmins wrote a script to recurse through internal jars from the /.m2/repository/ directory on our build server and then upload them into Nexus. However there were some bugs in the script, that resulted in people getting broken repositories.

The things we did wrong were:

1. Uploading jars into Nexus without specifying the pom file. By default, Nexus created a default pom file, but this only contained basic information like groupId, artifactId and version. No dependencies. 

Result: Transitive dependencies couldn't get resolved during builds in Maven, so compilation broke.

How We Found The Issue: Looking at the artifact directory in our local repo, and looking at the POM file. 

Fix: Update the command to deploy the file to specify both the Jar and Pom file.


2. Assuming that a .jar file was a java Jar. This was incorrect, because maven builds can also produce JAR containing source or javadoc. This resulted in the source or javadoc jar being mistakenly uploaded. 

Result: Builds broke because class files couldn't be found.

How We Found The Issue: Looking at the .jar file in local repo, opening it, and inspecting contents. No .class files - wrong jar upload

Fix: Update the command to exclude *-source.jar and *-javadoc.jar from deploys.




Thursday, 25 August 2016

Unit tests with mockito - how to verify that a parameter to a mock method call has an expected value



Use ArgumentCaptor, then in your verify() call for the method call you're setting up, use the argumentCaptor instead of the usual .class you'll be passing.

Then in your assert() to check the value, see if the argumentCaptor.getValue().get<field> has the value you're expecting

Basic idea is that you use ArgumentCaptor as the proxy to intercept the value the mock is getting.


Wednesday, 27 January 2016

JSTL transforms null BigDecimal to 0 and null String to ""


Was scratching my head why I was getting zero for a BigDecimal that I was returning as null, then realised I'd forgotten about JSTL behaviour that cleans up nulls to nicer values.

So anything extending type Numeric that is null gets shown as 0.

And anything that is a null String becomes a blank String.



As mentioned here:

After a bit of trial and error I discovered that the JSP tab library framework does a little bit of magic on known classes, such as Strings and Numericobjects. Classes of Numeric types that are null get converted to 0 andStrings get converted into the empty string ""

I discovered that if you change your internal value to anjava.lang.Object instead of a java.math.BigDecimal the magic doesn't know what to do and just passes null to your class.

Reference: 

http://andykayley.blogspot.com.au/2011/09/how-to-pass-null-value-to-custom-tag.html



Friday, 11 December 2015

Problem and solution: "Content not allowed in prolog" when loading XML as string, even without extra characters

I was parsing XML files in a unit test, but was doing it incorrectly.

I was loading them from classpath, then wanted to have them in a string and compare them using XMLUnit.


WRONG WAY

InputStream devStream = getClass().getClassLoader().getResourceAsStream("api-response--dev.xml");

String devXml = devStream.toString();


I was getting "Content not allowed in prolog" when I tried to parse this as XML, even though there was no BOM or extra characters in the source XML file.

Turns out I was doing it incorrectly. Because if you call toString(), you end up using the default encoding of your platform. 


RIGHT WAY


InputStream devStream = getClass().getClassLoader().getResourceAsStream("api-response--dev.xml");

String devXml = CharStreams.toString(new InputStreamReader(devStream, "UTF-8"));