Monday, October 7, 2013

Silicon Code Camp 2013: "12 Take-Aways: Managing the Unmanagable" Summary

This is the first in a series of posts about what I found out at the 2013 Silicon Valley Code Camp (#svcc).  This post is about the information presented in the presentation "12 Take-Aways: Managing the Unmanageable" by Ron Lichty (@RonLichty).  I feel compelled to disclose gain on my part; that there was a raffle for a free copy of his book "Managing the Unmanageable" (link below) which I won.  Just from reading a selection of 30 pages or so about "Managing Yourself" I can tell that the book is also really good.  With that in mind we can continue on to major points from the slides.

There is so much technical expertise expected of a programmer to possess, but so little management knowledge expected to manage programmers.  In many organizations a programmer is promoted to a manager of programmers with no formal training or even required reading!  Not even the Mythical Man Month (link below)!  Compare this to automotive companies where managers are sent for six weeks of just training in the lean methodology.  (There is going to be a summary of a presentation on lean start-ups in this series too).  Most software managers are not provided with a mentor or given clear tasks beyond the project deadlines.  These tasks are typically removing impediments to the team; setting goals and objectives for the team and team-members and advocating the process used for development.

Doing these tasks well and in different circumstances right now can be bolstered by rules of thumb (coincidentally in his book).  Some of these are that you should always be recruiting and bad hires happen to everyone.

Dealing with problem employees can be done via having an intervention, crafting performance plans, or letting the employee go.  There is also a book on just this subject, "Handling the Difficult Employee" (link below).  The goal of an intervention is to turn them around (and if that doesn't work they will typically leave on their own). This is the most time consuming option for preparation, the intervention itself and for the follow-up as well.  As for execution you state the problem behavior (have a problem with the behavior, not the person) and the impact of that behavior on the team.  Then let them vent, they will typically blame others for everything, this will take a lot of time (block off 4 hours).  Follow up with them weekly.

Another rule of thumb: follow up 1 on 1 weekly with ALL of your employees.

Get to know your people's personality types and coding styles, this will help with problems not showing up to begin with.  He almost suggests doing a full psych profile since not all programmers are alike.  Disciplines are different (system programmers vs web app guys vs mobile app guys), generations and ages vary, some people are morning people and some are night people, employees vs contractors, local or remote and cowboys ("get it done" whoCaresAboutBadStyleLikeHowLongVariableNamesShouldBe) vs farmers (cultivate good, clean code).  These personalities are who will work on the product.

At the start the concern about the product will be about scope, budget and schedule but at the end the question is "do people love it?"  To put it another way, "It's the Product, Stupid" (meme).  Getting a good product out can come down to leadership.

Leading by example happens, whether you like it (or want to) or not and take time for reviews of your progress.  Especially with people who have recently had a change in role.

What made you successful in one role can get in your way in another.  Needing the concentration to get into a flow state to code doesn't mesh with having an open door (e.g. "interrupt me whenever you need to") policy.  When they do come in you need to give them your complete focus though while balancing micromanagement vs fire-and-forget delegation.  In addition to leadership and listening you have to pay attention to motivations.

There is a difference between motivators and things that are not demotivators.  As an example low compensation is a demotivator but high compensation over good compensation isn't a motivator.  Motivators are things like making a difference, learning and growing, toys and technology, recognition and praise, having fun and having good relationships.  Especially with money, be careful what your reward.

You get what you measure is a rule of thumb and this applies to employee metrics.  Want a bloated code base?  Then you measure lines of code.  Want a terrible code base?  Then reward features and ignore efforts on refactoring.  Want people to be working for money instead of for passion?  Then reward them with money.  That applies when you're being managed as well.

The most important leader in your organization is your boss.  Assume that perceptions are real to those that have them and (again) focus on listening.  There were topics that he didn't cover; the runners up in the top 12 list and things that came up in discussion.

These topics included recruiting, the first day of getting a new hire, fostering a culture (there will be a post on that as well) and teamwork.  Covered during the discussions were topics like: how do you manage being a programmer AND a manager in a small company (block off a few hours of coding time a day, open door for the rest of the day); how you manage remotely (dig for problems, ask "what do you hate" or "how could I manage better"); self-reviews (if in a VERY small company) and what to do if people show up late for an 8 person meeting (bring delicious cookies, 7 of them).

Next in the line up is going to be about corporate culture.

Further Reading

Book: Managing the Unmanageable
Book: Handling the Difficult Employee
Book: Manage It!, the Programmatic Programmer book on management
Book: The Mythical Man Month
Book: Peopleware
Magazine: Harvard Business Review
Author: Danial Pink
Blog: ronlichty.blogspot.com

Tuesday, October 1, 2013

Here Be Dragons: Apache DeltaSpike on Google App Engine

I recently tried using Apache DeltaSpike, CDI extensions that are the official successor to Seam. On the Google App Engine.

Unfortunately, as of this writing (and version .4 of DeltaSpike) the library triggers the infamous Restricted Class error:

[INFO] Oct 01, 2013 11:59:04 PM com.sun.faces.config.ConfigureListener contextInitialized
[INFO] SEVERE: Critical error during deployment: 
[INFO] com.sun.faces.config.ConfigurationException: Factory 'javax.faces.context.FacesContextFactory' was not configured properly.
[INFO]  at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:330)
[INFO]  at com.sun.faces.config.processor.FactoryConfigProcessor.process(FactoryConfigProcessor.java:236)
[INFO]  at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:435)
[INFO]  at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:214)
[INFO]  at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
[INFO]  at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
[INFO]  at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
[INFO]  at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
[INFO]  at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
[INFO]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
[INFO]  at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
[INFO]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
[INFO]  at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
[INFO]  at org.mortbay.jetty.Server.doStart(Server.java:224)
[INFO]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
[INFO]  at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:249)
[INFO]  at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:306)
[INFO]  at com.google.appengine.tools.development.AutomaticInstanceHolder.startUp(AutomaticInstanceHolder.java:26)
[INFO]  at com.google.appengine.tools.development.AbstractModule.startup(AbstractModule.java:79)
[INFO]  at com.google.appengine.tools.development.Modules.startup(Modules.java:88)
[INFO]  at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:240)
[INFO]  at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:399)
[INFO]  at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
[INFO]  at com.google.appengine.tools.development.DevAppServerMain.<init>(DevAppServerMain.java:334)
[INFO]  at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:310)
[INFO] Caused by: javax.faces.FacesException: org.apache.deltaspike.jsf.impl.listener.request.DeltaSpikeFacesContextFactory
[INFO]  at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:710)
[INFO]  at javax.faces.FactoryFinder.getImplementationInstance(FactoryFinder.java:572)
[INFO]  at javax.faces.FactoryFinder.access$500(FactoryFinder.java:140)
[INFO]  at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:1120)
[INFO]  at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:379)
[INFO]  at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:328)
[INFO]  ... 24 more
[INFO] Caused by: java.lang.reflect.InvocationTargetException
[INFO]  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[INFO]  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
[INFO]  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[INFO]  at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
[INFO]  at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(Runtime.java:127)
[INFO]  at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Runtime.java:135)
[INFO]  at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:690)
[INFO]  ... 29 more
[INFO] Caused by: java.util.ServiceConfigurationError: org.apache.deltaspike.core.spi.config.ConfigSourceProvider: Provider org.apache.deltaspike.core.impl.config.DefaultConfigSourceProvider could not be instantiated: java.lang.NoClassDefFoundError: javax.naming.InitialContext is a restricted class. Please see the Google  App Engine developer's guide for more details.
[INFO]  at java.util.ServiceLoader.fail(ServiceLoader.java:224)
[INFO]  at java.util.ServiceLoader.access$100(ServiceLoader.java:181)
[INFO]  at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:370)
[INFO]  at java.util.ServiceLoader$1.next(ServiceLoader.java:438)
[INFO]  at org.apache.deltaspike.core.util.ServiceUtils.loadServiceImplementations(ServiceUtils.java:55)
[INFO]  at org.apache.deltaspike.core.api.config.ConfigResolver.resolveConfigSources(ConfigResolver.java:224)
[INFO]  at org.apache.deltaspike.core.api.config.ConfigResolver.getConfigSources(ConfigResolver.java:203)
[INFO]  at org.apache.deltaspike.core.api.config.ConfigResolver.getAllPropertyValues(ConfigResolver.java:160)
[INFO]  at org.apache.deltaspike.core.util.ClassDeactivationUtils.initConfiguredClassDeactivators(ClassDeactivationUtils.java:152)
[INFO]  at org.apache.deltaspike.core.util.ClassDeactivationUtils.getClassDeactivators(ClassDeactivationUtils.java:143)
[INFO]  at org.apache.deltaspike.core.util.ClassDeactivationUtils.initDeactivatableCacheFor(ClassDeactivationUtils.java:88)
[INFO]  at org.apache.deltaspike.core.util.ClassDeactivationUtils.isActivated(ClassDeactivationUtils.java:73)
[INFO]  at org.apache.deltaspike.jsf.impl.listener.request.DeltaSpikeFacesContextFactory.<init>(DeltaSpikeFacesContextFactory.java:42)
[INFO]  ... 36 more
[INFO] Caused by: java.lang.NoClassDefFoundError: javax.naming.InitialContext is a restricted class. Please see the Google  App Engine developer's guide for more details.
[INFO]  at com.google.appengine.tools.development.agent.runtime.Runtime.reject(Runtime.java:51)
[INFO]  at org.apache.deltaspike.core.impl.util.JndiUtils.<clinit>(JndiUtils.java:51)
[INFO]  at java.lang.Class.forName0(Native Method)
[INFO]  at java.lang.Class.forName(Class.java:186)
[INFO]  at com.google.appengine.tools.development.agent.runtime.RuntimeHelper.checkRestricted(RuntimeHelper.java:70)
[INFO]  at com.google.appengine.tools.development.agent.runtime.Runtime.checkRestricted(Runtime.java:64)
[INFO]  at org.apache.deltaspike.core.impl.config.LocalJndiConfigSource.getPropertyValue(LocalJndiConfigSource.java:53)
[INFO]  at org.apache.deltaspike.core.impl.config.BaseConfigSource.initOrdinal(BaseConfigSource.java:54)
[INFO]  at org.apache.deltaspike.core.impl.config.LocalJndiConfigSource.<init>(LocalJndiConfigSource.java:39)
[INFO]  at org.apache.deltaspike.core.impl.config.DefaultConfigSourceProvider.<init>(DefaultConfigSourceProvider.java:49)
[INFO]  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[INFO]  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
[INFO]  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[INFO]  at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
[INFO]  at java.lang.Class.newInstance0(Class.java:372)
[INFO]  at java.lang.Class.newInstance(Class.java:325)
[INFO]  at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:362)
[INFO]  ... 46 more