Sunday, February 28, 2016

Satisficing

Satisficing is something you actually use all the time when you make decisions. You do this all the time whether you are aware of it or not. The word itself is a combination of satisfy and suffice. In short it means to come up with solutions that are good enough (sufficient) for the problem.

In the real world, the optimal solution for something is usually not realistic because the cost of doing the optimal solution is too expensive. If you need a dry cleaner, the ideal is to find the one with the best skills for the least price within the area you are willing to go. However, actually finding this is not practical; there are usually too many options to choose from. Instead you should just settle on the one you find first that meets your criteria. You need to do this otherwise it will take all of your time. There is not enough value to justify getting from one good enough to satisfy your needs to the optimal one. 

We do this all the time without even thinking about it. When we clean our house we will vacuum the carpets and make sure things are put away properly. Too some that alone is not satisfactory and they will wipe down the kitchen tops or clean the dust under the couch. But at sometime we all have to make a decision on what is good enough. There is always going to be a way to optimize more and make things cleaner but it is not worth the effort. Its just not worth it to get down on our hands and knees with a scrub in some obscure part of the house and scrub down a minuscule amount of grime on an already clean floor. We all decide at one point that it is clean enough and stop.

This happens all the time in business situations. I was having a conversation with a couple co-workers and one was stunned why management would not invest more time in improving some analytical report which she claimed could be at least 5% more accurate. I wasn't surprised that the manager decided that the report was good enough and would rather allocate attention to something else.

I see this situation all the time in software development. An engineer who had some issues with management explained to me that "management just doesn't understand, we engineers want this to be of high quality and as good possible. Management just wants to get this out the door." Both management and engineering have different levels of defining what is "good enough". Whats interesting is that this conflicts with an idea set in one of the best software management books that high quality is tied to self worth and enjoyment:
"Since their self-esteem is strongly tied to the quality of the product, they tend to impose quality standards of their own. The minimum that will satisfy them is more or less the best quality they have achieved in the past. This is invariably a higher standard than what the market requires and is willing to pay for.""Your marketplace, your product consumers, your clients, and your upper management are never going to make die case for high quality. Extraordinary quality doesn't make good short-term economic sense. When team members develop a cult of quality, they always turn out something that's better than what their market is asking for. They can do this, but only when protected from short-term economics. In the long run, this always pays off. People get high on quality and out-do themselves to protect it."
I think this is a core concept highlighting a natural point of conflict between makers and managers.

Wikipedia has a good example of satisficing being used in consensus building when the group looks towards a solution everyone can agree on even if it may not be the best:
Example: A group spends hours projecting the next fiscal year's budget. After hours of debating they eventually reach a consensus, only to have one person speak up and ask if the projections are correct. When the group becomes upset at the question, it is not because this person is wrong to ask, but rather because the group has already come up with a solution that works. The projection may not be what will actually come, but the majority agrees on one number and thus the projection is good enough to close the book on the budget.
It is important for each person to understand this concept of decision making. For engineers to understand the business requirements and not try to over-polish something that doesn't need it while at the same time for management to understand that high quality has its own rewards and possibly some unexpected benefits (Peopleware claims high quality = high productivity rather than an inverse). No one is questioning that famous Facebook poster that reads "Done is better than perfect". We just need to put some thought into what "Done" means.



Sunday, February 21, 2016

Sleep Hacking

I've always wanted to become a morning person. On paper, it seems like there shouldn't be (in terms of productivity) any difference between early risers and night owls. However, I like the feeling of getting things done early and the feeling that the whole day is ahead of me. In the evenings, my energy is usually lower and I tend to do more wasteful activities. I've pictured myself jumping out of bed in full Carpe Diem mode and getting at it. So I've made an effort over the last year to change my habits and wake up early:

1) Don't have too much caffeine. I'm particularly caffeine sensitive so I make sure to have just one cup of coffee in the mornings and that's all. Anything afternoon will disrupt my sleep pattern.

2) Natural light alarm clock. I had bought one of these lights to simulate natural light and wake me up slowly. This didn't really help since I just don't notice the light when I am asleep. I found the natural alarm clock useless and resold it on Craigslist.

3) Put the alarm clock on the other side of the room. This was the single most important move. If you put the alarm clock in a strategic place where you can't snooze it you will be forced to get up and turn it off.

4) There are other considerations to where you put your alarm clock besides out of reach. You'll want to put it in a place that will trigger your morning habit routine. For example, if you can put it near your toothbrush the next step would be to pick it up and start brushing. And once there you probably won't be be getting back into bed.

5) So you should have a morning routine. When you wake up your mind and body is not warmed up and you shouldn't be thinking about what to do next. You should instinctively know what to do. This takes first preplanning what needs to be done and then setting triggers to help you develop the habit. For example, placing the coffee pot out in a convenient noticeable spot.

My morning tasks:

Wake up and shut off alarm.
Start coffee maker
Study language vocab
Check email
Cook food
Get dressed

I've conveniently stuck in study language vocab by putting the app in a more prominent position than email.

6) Prepare to sleep at a set time. If my bed time is 10:00pm then I tell myself that I am 15 minutes past my bedtime when it is 10:15pm. This also means that I have to start the wind down process 15 minutes ahead of time.

7) If you are used to sleeping at midnight You aren't going to be able to just change and sleep at 10pm all of a sudden. You won't fall asleep and your body will feel tired during wake hours. When I came back from an extended trip to South America (East coast time) I made sure to not go back to my original time but rather the earlier time that my body was already used to. If you aren't able to take a trip you can do something similar by taking advantage of daylights savings time and wake up normally instead of sleeping in for an hour.

8) I was recommended the desktop program F.lux which is supposed to change the colors of the screen to more soothing colors to prepare you to fall asleep instead of harsh bright colors that keep you awake. To be honest I didn't notice a difference in improving my sleep. It did however function as another alarm clock in which I decide to turn off the laptop once the background change happens.

9) Change of mindset: Ashley Zahabian mentions in her youtube video about rising early that caught my attention. 

"Whats your reason to wake up? If you don't have one why wake up right? But the problem is the process is backwards. You have to wake up first."

I've personally found this to be true for me. If I don't have that day planned I start trying to figure it out in bed and it tends to be foggy since my body and mind is not warmed up yet. I have to wake up FIRST and THEN the day will unravel. 

So that's a summary of what I did to switch from a night owl to a morning person. So far I enjoying the change.

Monday, February 15, 2016

Refactoring code: Factory Pattern With Generics

Most of us can look at the following example and recognize that it could be written much more elegantly. But lets look into exactly why that is the case and how we can fix it.


The first clue that something is wrong is that IntelliJ highlights both the lines parser.doSomething() in yellow with the warning:
Unchecked assignment: 'java.util.List' to 'java.util.List'. Reason: 'parser' has raw type, so result of parse is erased.
So what does this mean?  Java does type checking at compile time. Since parser was declared with a  raw type, the Java compiler has no way to know the type of the List returned by parse()

But whats all the fuss about? Is this just about removing annoying yellow lines and compiler warnings? Well its a bit deeper than that, since the warning is actually pointing to a flaw in the design.

The reason why the developer used the raw type was because she wants to use the same parser to parse both InvoiceLine and InvoicePaymentLine types. If you actually add a type to the Parser, the warning will go away for one of parse calls but have a compilation error for the other.

One way (not the only way) to fix this is to have a common type for both InvoiceLine and InvoicePaymentLine. Lets make a common interface called Invoiceable. That way we can declare the parser as Parser parser.

That combined with changing the Lists to the same type and a single parse method will get rid of the initial warnings that we saw:

Furthermore the two loops are essentially doing the same thing. Instead of repeating them. Lets just iterate over our List of Invoiceables and set the invoice. To do this we have to add a setInvoice function on the interface. I also removed the check to isEmpty(). Its good practice to not return null and just an empty List making empty and null checks unecessary and cleaning up the verbosity of the code.

And finally, all of the if-then statements are just figuring out how to create a parser. Abstracting out the creation of objects is a good candidate for a Factory method.
The result of main looks like this.

And Beyond 


It looks much cleaner than before and the logic is much easier to follow. As with any refactoring it depends on your situation on what is good enough for the moment and how you think the code may change. You can always add more layers of abstraction or determine that when you see more use cases.

Saturday, February 6, 2016

Upgrading to log4j2

 As you may already know log4j has reached end of life. But don't worry! log4j2 is here to the rescue and its way better. I've recently have been working on a migration from log4j1.xx to log4j2 in a maven managed Spring 4 app. Here are some of my findings.

Advantages of log4j2

There are lots of them but what I find the biggest reason for this upgrade is the asynchronous loggers & appenders. This offers a huge performance boost because now your application performance and your disk are now decoupled. (You could actually get async appenders working in log4j1, but now there is a performance boost)

The second thing that I thought was nice was allowing lambda expressions. This will lazily evaluate an expression only if it conforms to the log level threshold. This means that wrapping the code with isDebugEnabled() is unnecessary. Some orgs may feel it unnecessary now to use a logging abstraction like SLF4J

There's also other goodies like custom log levels and markers.

One very practical tip is Using log4j2 ThreadContext to enable per request debugging

Example log4j2 configuration


The above has a rolling file and syslog appender with async logging. Another way to turn on async logging for all appenders is to drop the LMAX Disruptor jar onto the classpath and set the Log4jContextSelector parameter to org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

In addition it shows how to setup a syslog appender. We use this to centralize logs in rsyslog and provide the logs to Logstash.

Here's hoping you make the transition to log4j2, theres a lot of improved features to look forward to.