-
2-3 years of software development experience using
C# in web applications - Possess good communication skills
- Oracle or SQL Server experience
- Working knowledge of common design patterns
-
Working knowledge of scripting languages such as
Ruby or Perl - Report to the Director of Development
- Work in an Agile/Lean environment
-
Provide technical analysis and designs for
features -
Incrementally estimate and implement features
from feature backlog - Develop automated tests for implemented features
-
Develop skills with ASP.NET, C#, Silverlight,
NHibernate, Lucene.NET, Subversion, GIT, TeamCity, Ruby, WIX, ActiveReports,
Oracle, SQL Server, DDD, CQRS, SOLID, TDD, BDD and more
Thoughts on Hiring Developers
Gabriel posted this rant regarding his frustration with trying to find the right developer talent for positions that we were trying fill. At the time, I was the final decision maker regarding these interview candidates, so I thought I would offer my perspective.
First of all, let me say that we did find the types of individuals we wanted. It just took time and work. We made offers to a couple of individuals who turned us down for counter offers. I would imagine we also passed on some developers who could have been really good. This would be because either we did a poor job of asking the right questions and learning about the candidate or the candidate did a poor job of selling us that they are the right person for the job. Regardless, if they did not make an impression, they did not get an offer. It’s too expensive to give a person an opportunity and have them turn out to be the wrong person which causes the team’s productivity to suffer.
There is some discussion in the comments of Gabriel’s post about “low quality” developers are not able to land “high quality” jobs because those jobs require you to already be highly skilled. I do not think this is true. A lower skilled individual just has to try harder. I am impressed with candidates that I meet who are currently working in a lower skilled development position and have the desire to move to a higher one. First it shows that they acknowledge their skill level. Second it shows that they have enough interest in development to want to become better. If you want a shot at something, show that you deserve it.
It is very true that a great deal of interviewers do a poor job of interviewing. Sometimes the interviewer does all the talking instead of asking good questions. Sometimes the interviewer asks questions about something new that they just learned themselves. Regardless how the interviewer conducts the interview, it is important for the candidate to “wow” the interviewer with at least one thing. It can be something technical, team related, enthusiasm, … something. If a candidate leaves and fails to do this, then it may the interviewer saying “I am not sure”, which then they will often move on to another candidate.
With the interviews that Gabriel described, we tried to give the candidate every opportunity to wow us. Most did not. I wish they did. I believe with most candidates, we gave them feedback and what we thought they should be learning in the hopes they would call us six months later and let us know of they’re progress. Maybe some will?
Below are a few thoughts that came to mind as factors when narrowing down the candidates.
Honesty
What I mean by honesty is whether or not the candidate is honest to you and themselves about their knowledge and skill. Do they put things on their resume that they do not really know? A person may tailor their resume to be specific to a particular job application, but they should not try to make themself look smarter than they are because it will ultimately hurt them later. I understand that most people are capable of learning anything given the opportunity, but padding their skills makes them look dishonest. A great deal of hiring managers are not extremely technical and will throw out resumes if they do not contain certain buzz words, but those are probably lowered skilled jobs anyway. Higher skilled development positions are likely to have higher skilled interviewers.
If I ask a candidate about a skill on their resume and they explain to me that they’re a beginner in that skill, I am OK with that answer as long as they have some experience with the skill and they are honest about their level. But if the person tries to fake it and try to make me think they know more than they really do, then I have already made my decision that this person is not the right person for the job. How can I trust someone to do a task properly if I cannot trust them to tell me what they know and do not know?
Commitment
Though some shops are forty hours a week shops, many are not. It is important to ensure that expectations regarding level of effort are well understood between the candidate and the employer. If extra hours need to be worked, then how much and how often? Is the candidate willing to commit to this? How will it look if one team member consistently works the minimum while others are working extra? It’s important that the team have a similar level of commitment or they will not really be a team.
Technical Skill
All candidates possess as least some technical skill (we hope) but technology is so broad and and there are millions of different ways to solve problems. The chances that a candidate’s skills match perfectly are very slim. There will be gaps between what a new hire knows and what they need to know to perform their work. Experienced programmers will be expected to fill those gaps more quickly than less experienced programmers. The challenge of a hiring manager is to determine if the gaps are acceptable for the given candidate and open position. The challenge of the candidate is to convince the hiring manger that they will easily fill those gaps.
On / Off The Job Training
I think most developers would say that they could learn just about anything given the opportunity and we have all had the opportunity to learn a great deal of things “on the job”. But I have always felt that it was my duty as a professional to also learn things outside of my job. I want to know if a candidate is willing to invest in themselves before I invest three months to train them. I want to make sure I get the best return on investment that I can get. A candidate that demonstrates that they will work extra hard to get up to speed makes me feel good about investing in them.
When a candidate is coming from a lower skilled position, I want to know what are they doing currently to improve themselves. Yes, we all are busy, but a great deal of us still find time to read outside of work, if not code. If the under skilled candidate is not currently working to increase their skills, then I am sorry that I do not have any interest in teaching them. They have to make an effort more than just saying “I want”.
Compensation
Of course everyone wants to get as must money as they can and every company wants to spend as little money as possible, but with higher compensation, comes higher expectations. Salary negotiation is about aligning those expectations. If the salary is too low, the new hire will not be happy and end up leaving for more money later. If the salary is too high, then the new hire is at risk if their work does not live up to company expectations. There has to be a balance. Some companies may have unreasonable expectations for an offered salary. Some candidates may have unreasonable salary requirements for their skill level. Even if a person has several years of experience, they may need to lower their compensation requirements if they are considering moving into an area where they are less experienced.
Compensation can be based on other factors besides experience and technical skill such as innovation, commitment, work quality and leadership. You do not have to be good at everything but you need to be good at something.
Conclusion
Hiring the right people is hard. Searching for the right job is hard. Having the right attitude and expectations can make it easier, but nothing can make it easy. Good luck to all!
Big Software Rewrites
It is well known that big software rewrites are often failures. They fail because they always look easier than they really turn out to be. To replace a system that has been around for years is likely to take years to rewrite. Plus you have to add in all that time required to fix new bugs, add the features that were missed, and handle a whole new set of discovered edge cases. While the rewrite is happening, the existing product is not getting the attention it needs. Bug fixing and enhancements stop and customers become frustrated. This can give the competition an advantage. They may gain market share by delivering features customers want and need while you spend two plus years rewriting and stabilizing your product.
If you haven’t already read it, check out “Things You Should Never Do, Part I” by Joel Spolsky from over 10 years ago that is still very relevant.
.NET Software Developer Position in Austin
We’re currently looking for an outstanding individual to fill an open position on our development team. You can find the ad on our web site at http://www.topazti.com/company/topaz-jobs. I’ve also posted it below for convenience:
TOPAZ Technologies is an established leader in the
development and support of software solutions for medical research. The company has a solid foundation of
clients including leaders in the pharmaceutical, biotech, university,
government, and private research organizations.
TOPAZ is privately owned and offers excellent benefits to employees.
Requirements**
Responsibilities
TOPAZ is a dynamic company where we strive to maintain a
fun, team-oriented atmosphere. We are looking for motivated, self-starting
individuals who can grow with the company. Salary will be commensurate with
experience. Final candidates will be subject to a background check.
Fluent Silverlight – Auto Wiring INotifyPropertyChanged
In Gabriel’s introductory post for Fluent Silverlight, he showed that the code typically associated with implementing INotifyPropertyChanged can be reduced to a simple auto property. This can really improve the clarity of a large class as well as save some typing. I’m going to show you how to get it setup.
INotifyPropertyChanged
First lets talk a little about normal INotifyPropertyChanged. This is an interface that is typically implemented on a ViewModel that you wish to participate in two way data binding between itself and some sort of DependencyProperty which typically lives on a control. The interface declaration looks like:
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
public class MyViewModel : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
if (value == name) return;
name = value;
OnPropertyChanged("Name");
}
}
private int age;
public int Age
{
get { return age; }
set
{
if (value == age) return;
age = value;
OnPropertyChanged("Age");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
IAutoNotifyPropertyChanged
We got to thinking that if we could intercept the changes to the properties (AOP), then we could automatically throw the PropertyChanged event. One way to do this is to use Castle.DynamicProxy (the Silverlight edition). DynamicProxy allows us to create a runtime generated subclass of our ViewModel. The generated subclass allows interception of any virtual member where we can chose to do what we please. To get it all started, we needed an interface that would allow us to trigger the event:
public interface IAutoNotifyPropertyChanged : INotifyPropertyChanged
{
void OnPropertyChanged(string propertyName);
}
Next we updated our ViewModel to implement the new IAutoNotifyPropertyChanged interface and removed all the extras:
public class MyViewModel : IAutoNotifyPropertyChanged
{
public virtual string Name { get; set; }
public virtual int Age { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
As you can see, there is a lot less noise here and we don’t have the magic strings for the property names laying around. Also note that we made the properties virtual so that they can be intercepted. To actually make the auto wiring work, we have to create an instance of the ViewModel class (actually it’s a generated subclass) using our AutoNotifyPropertyChangedProxyCreator. I’m not sure if we’ll stick with that name, but it will do for now. Take a look at the following little test:
[TestFixture]
public class when_creating_viewmodel_with_creator
{
private MyViewModel model;
private string lastPropChanged;
[SetUp]
public void SetUp()
{
model = new AutoNotifyPropertyChangedProxyCreator().Create<MyViewModel>();
model.PropertyChanged += (s, e) => lastPropChanged = e.PropertyName;
lastPropChanged = null;
}
[Test]
public void should_send_property_changed_for_given_property()
{
model.Name = "test";
Assert.That(lastPropChanged, Is.EqualTo("Name"));
Assert.That(model.Name, Is.EqualTo("test"));
}
}
Because the proxy is a subclass, we can treat it as it’s original type MyViewModel. As the Name property changes, it fires the PropertyChanged event which is wired to update the lastPropChanged field.
Summary
INotifyPropertyChanged is a handy interface for doing two way data binding but it causes a lot of extra noise in your classes. In Fluent Silverlight, we have introduced the IAutoNotifyPropertyChanged interface which is used in conjunction with AutoNotifyPropertyChangedProxyCreator which uses Dynamic Proxy to intercept the calls and auto throw the PropertyChanged event. This allowed us to reduce the noise and completely remove the magic strings typically associated with standard INotifyPropertyChanged.
In a future post I’ll demonstrate how you can do other things with this such as ignore certain properties, tap into the interception to execute methods and have an IoC container handle the proxy creation.
Simple Code Navigation with ReSharper
Here’s a quick 5 minute screen cast that demonstrates how you can use ReSharper to get where you want to be in your code. If you haven’t tried ReSharper yet, I highly recommend that you download the free trial and give it a spin.
Don’t Waste The Time We Have Now
I almost titled this “Get Things Done” but this post is not about how to do things. This post is about minimizing waste associated with distractions from non work related activities. I’m talking about things like Instant Messenger, Twitter, Skype, Facebook, personal phone calls, texting or anything else that is a distraction.
Some of the online tools can be used for work related activities (and I do used them), but they can also be major productivity killers. I bet that 90% of what happens on these things is noise. I don’t have any statistics to back that up, but from my own experiences, what happens on there is mostly waste. For myself, I have enough work related distractions without piling on extras. You don’t notice how much time you actually waste until you get so busy that any unnecessary distraction becomes a painful thing.
If you’ve had the opportunity to do some real pair programming, then you can appreciate minimizing distractions. One of the reason pair programming works, is that it keeps both parties engaged in the work. Even a simple phone call or text message to either party is a distraction. It actually even feels rude. After a good day of pairing, you feel exhausted because you put in a real day’s work. You were engaged the entire time. Why don’t we hold ourselves to the same standards when we are programming solo?
Don’t get me wrong. I’m not saying that we shouldn’t take breaks and have our minds think about other things once in awhile. The fact is that we’re going to have non worked related distractions. The real point of this post is to remind everyone that in economic times like these, we cannot afford to waste the time we have now. If a company of 100 people waste 20 minutes a day on non worked related activities, then that is over a man week that has been wasted within that day. Wasted, gone, vanished, can’t get it back. The time you waste today, may mean someone’s job tomorrow (if not your own).
Pablo welcomes Gabriel Schenker
I’m happy to announce that Gabriel Schenker has accepted an invitation to join Los Techies. You may know Gabriel as the man behind the NHibernate FAQ Blog or contributor to many of the software related community lists. He is an expert in didactics and methodology. He is very passionate about software development and the software community.
Look for his LosTechies posts at http://gabrielschenker.lostechies.com
Welcome Gabriel!!!
PTOM: The Composite Design Pattern
The Composite Design Pattern
This post talks about the Composite Design Pattern and is part of Pablo’s Topic of the Month – November: Design Patterns. A Composite is a tree structure where each node can be represented as a common type so that they can be acted on in a consistent manner, regardless of their concrete implementations. This allows a consumer of the composite to avoid the complexity of having to distinguish the objects individually. I believe that the posts for PTOM are going to centered around a coffee shop, but I’m having a difficult time thinking of a good composite example around that, so let’s say I’m building coffee machines instead.
Lets pretend that I have a model of a coffee machine and all of its parts. Many of the parts are logical and are made up of only child parts. I might have a class that looks something like the following (simplistically implemented for example purposes):
public class CoffeeMachine
{
public FluxCapacitor FluxCapacitor { get; set; }
public PowerCord PowerCord { get; set; }
}
public interface IPart
{
IEnumerable<IPart> GetChildParts();
}
You will notice that the IPart returns child instances of other IParts. This gives us a recursive structure and lets us act on that structure as a composite. By implementing this interface on all of our parts, when can then walk the hierarchy and perform operations without knowing the details of each implementation. We can implement this on our CoffeeMachine and our other parts like the following:
public class CoffeeMachine : IPart
{
public FluxCapacitor FluxCapacitor { get; set; }
public PowerCord PowerCord { get; set; }
public IEnumerable<IPart> GetChildParts()
{
yield return FluxCapacitor;
yield return PowerCord;
}
}
public class FluxCapacitor : IPart
{
public Switch Switch { get; set; }
public PowerBooster PowerBooster { get; set; }
public IEnumerable<IPart> GetChildParts()
{
yield return Switch;
yield return PowerBooster;
}
}
public class PowerCord : IPart
{
public IEnumerable<IPart> GetChildParts()
{
yield break;
}
}
Now we can easily build a part list generator that uses a recursive method to walk through the hierarchy and outputs the names of the parts.
public class PartListGenerator
{
public void OutpAllParts(IPart part, TextWriter textWriter)
{
OuputAllPartsByLevel(part, textWriter, 0);
}
private static void OuputAllPartsByLevel(IPart part, TextWriter textWriter, int level)
{
textWriter.WriteLine("{0}{1}", new string('t', level), part.GetType().Name);
foreach (var childPart in part.GetChildParts())
{
OuputAllPartsByLevel(childPart, textWriter, level + 1);
}
}
}
By running our CoffeeMachine through this class, we end up with something similar to the following output:
CoffeeMachine
FluxCapacitor
Switch
PowerBooster
PowerCord
Pablo’s Topic of the Month – November: Design Patterns
Pablo’s Topic of the Month – November: Design Patterns
Back in April, we announced we would be doing a PTOM on Design Patterns. It turned out that April was a busy month for all of us and we didn’t live up to our announcement. I think we’re going to claim it as a sad April fools joke. During the course of this month we will revisit our previous topic with the exception that the patterns will not just be patterns from ‘Design Patterns: Elements of Reusable Object-Oriented Software’ (Addison-Wesley. ISBN 0-201-63361-2) , but from various sources which we believe are relevant to the types of programs being written today.
If you haven’t already, please consider subscribing to the Los Techies Main Feed so that you can see the various post from all the Los Techies bloggers.
The main feed is here: https://feeds.feedburner.com/lostechies
What is a Design Pattern?
A Design Pattern is exactly what it sounds like. It’s a design that can be applied over and over again, forming a pattern. The Wikipedia page for Design Patterns describes one as
a general reusable solution to a commonly occurring problem in software design. A design pattern is not a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations.
By using Design Patterns, we can better standardize our designs makes them easier to understand. Design Patterns give us a common vocabulary in which to use in communicating software designs. Without them, we would have a difficult time in explaining and documenting our ideas.
Posts on Design Patterns
We will update this area with links to the posts as they happen.
PTOM: The Decorator Pattern by Sean Chambers
PTOM: The Composite Pattern by Ray Houston
PTOM: Command and Conquer Your UI Coupling Problems by Derick Bailey
PTOM: Bend 3rd Party Libraries to Your Will With the Adapter Pattern by John Teague
PTOM: Descriptive State Enumeration by Derick Bailey
PTOM: Visitor Design Pattern by Jason Meridth
Udi’s SOA Class Made Me Smart
Chris challenged me to write a post showing how smart I am after taking the class. 😉 While I know that “made me smart” is completely unbelievable, I did manage learn a great deal.
I’m slow to getting around to this post, but little over a week ago I finished up Udi Dahan’s week long class called “Advanced Distributed Systems Design using SOA & DDD”. As Aaron has already stated, it was awesome. The class was very well put together. The materials were clear and concise and Udi did a fantastic job presenting it. It was a good mixture of lecture, coding, and question and answer. I fully expected that I would be taking notes like crazy, but it was so well laid out that the only thing I wrote down the entire course was what I wanted for lunch. Udi provided us with all the lecture materials and everyone has access to all of the samples which are in the nServiceBus trunk.
Now I know why Udi is the “Software Simplist.” I was amazed to find that all the code and solutions were indeed very simple. Your day to day DDD code doesn’t change (if you’re doing it well). All the hard stuff is dealt with at the bus level. You as the architect need to know what’s going on so that you can apply the patterns appropriately, but a developer in the domain should not be writing code that deals with things like threading. If you are, you’re doing it wrong. The patterns that Udi presented keep things simple by isolating complexity so that it doesn’t creep into your day to day code. The domain code looks the same if it’s running in a single process or if it’s running in 100 processes.
Udi kept saying that the code is simple, but defining the right boundaries is the hard part. Often the questions we gave Udi were solved by diving deeper into the real business requirement and giving the business choices as to what their requirements really mean in terms of performance, latency, durability, etc. You get into trouble when you try to make a technical problem out of what should be a business decision.
Two great quotes from the lecture materials:
Best practices have yet to catch up to “best thinking”
Technology cannot solve all problems
Good SOA is not about applying one single thing over and over again. It’s about knowing your requirements, your options, and planning accordingly. I feel lucky that I got to spend a week with Udi and absorb some of this. I highly recommend that you attend his class if your doing or thinking of doing distributed systems.
In the coming months, I plan to start working on some SOA projects at TOPAZ and applying what I have learned. I hope to be able to blog about my experience and that Udi will correct me when I say something incorrect. 😉
subscribe via RSS