I Believe...

A recent reorg at my company left me with a new manager - and a different approach to software development than my team had been previously following.  Our new approach is one that I don’t necessarily agree with, but it led me to think about - and reevaluate -  those tenets of software development that I think are important and that I believe lead to increased quality and productivity.

This post will consist of fairly high level discussions about how to organize code, teams, and projects - but contain very little actual code.

Many of these ideas will not be my own.  They are mostly ideas I’ve learned from others and their willingness to share their experiences with me.  They are, however, ideas that I’ve practiced and hardened as I’ve worked to build my own ideal environment for delivering value through software.

Many of these ideas I now take for granted as commonplace (even though they aren’t).  I felt a need to document them anyway - so people can understand what to expect (and what is expected) on teams I’m working with.

I Believe... the only constant is change

Technology Change

Working in technology, things change fast.  Five years ago (2007), I was working in Java and creating user interfaces in JSF.  Limitations with that technology led me to consider Flex - which at the time I considered superior to AJAX because it seemed to eliminate any JavaScript browser incompatibilities I’d need to deal with.  Since that time, JavaScript support in browsers is much better and Javascript libraries like JQuery have emerged to greatly reduce (or gracefully deal with) browser incompatibilities.  During the same time, Apple essentially killed Flex and Flash by not supporting it on the iPhone.  Today, smartphones and tablets are radically changing the way people access the internet - allowing possibilities for interactions that we didn’t think much about 5 years ago.

This is a long way of saying - attaching your product or development team to a single technology stack doesn’t seem to make much sense.  Things change - quickly.  Technology decisions made today, might not look so good 6 months or a year from now.  Mandating that all of your solutions must use the same technology limits your ability to react to changes in the market.  You’re preventing your teams from selecting the best technology fit for the task they’re working on (it's kind of like trying to tighten a phillips head screw with a flat head screwdriver - you can do it, but you’d be better off choosing the best tool for the job and using the phillips screwdriver).  Reluctance or delays in making much needed technology changes kills productivity.  Team morale suffers as developers realize they could be doing much more for their users.  I’ve been on teams that have struggled for years attempting to support technology that was no longer a good fit - but for political reasons or pride - management was reluctant to replace.

It doesn’t have to be like this.  Expect and embrace technology change - it’s going to happen.  Allow teams to select the best tool for the job - it will make your products better, your teams more productive - and most importantly - your users happy.

Requirements Change

An entirely different type of change, is a change in user requirements.  Some people might refer to this as scope creep, but it’s inevitable.  As you learn more about the product you're designing, as you talk to more people and hear different perspectives, as more people gain experience in using your tool - your initial vision for the product is going to change.  It’s going to happen - how do you deal with it?

I’m going to talk about these in more detail later, but I think there are a few basic things you can do to help deal with these changes:
  • Keep your software loosely coupled.  Reduce dependencies between your objects, libraries, and on specific technology - hard dependencies limit flexibility to change.
  • Build automated tests. Automated tests give you the confidence to change code without breaking other parts of the system.
Again - if we expect, embrace, and plan for requirements changes from the outset - our software will be flexible, our products will easily adapt to market changes, and our users will thank us for our ability to quickly provide enhancements.

I Believe... failure is OK (and failing fast is better)

Thomas Edison said "Genius is one percent inspiration, ninety-nine percent perspiration."  Why do you think he was sweating 99% of the time?  It’s because he was failing - or rather he was learning things that didn’t work.  Trying and failing is how we learn.  It’s how we innovate.

Please don’t confuse or misinterpret what I’m saying here.  Failure because you’re lazy, because you ignore what your users are telling you, because you don’t effectively test your code, or because you don’t do your due diligence - is never OK.  Failure for any of those reasons is always bad.  What I’m talking about is the freedom explore new and innovative ways of doing things - and have it be OK if it doesn’t totally work out.

In this context - similar to change - we should expect and embrace at least some level of failure.  It’s OK to fail - as long as we learn from it.  Permission to fail is permission to explore other avenues - to look for a better way to do things.

If a team is not failing at least a little, it’s probably a sign that they aren’t pushing themselves - or being aggressive enough.  They are likely making “safe” estimates and decisions to avoid the (mistaken) impression that they’re not doing their job.  But the opposite is really true - by playing it too safe, they’re not going to try new ideas that could separate your product from the pack. There will be little innovation and your solution will likely lag behind others in the market.

The trick making this approach work is - limiting your time to failure (failing fast).  The longer it takes you to fail, the more time you’ll spend doing the wrong thing - and the less time you’ll be left with to do it correctly.  And like we discussed with change - one way to plan for these (fast) failures is to keep your code flexible.  Build the ability into your code to plug in different implementations or ideas - and to allow side by side comparisons of different approaches.  Continuously experiment, test, and measure.

It’s OK to fail - just do it with purpose - and please do it quickly!

I Believe... users come before anything else

We can write the most beautiful code, design stunning user interactions, use the latest technology - but if we’re not giving our users what they want (or making them more productive), we’ve failed.  

Early in my career, I’ve was guilty of this.  I was feature driven instead of user driven.  I was focused more on using trendy technologies instead of making changes that were in the best interest of my users.

After one particularly long development cycle, I was super proud of some user interface changes I made to my application.  But when I rolled it out to my users, they universally hated it!  And I rolled it back to the previous version.  It was heartbreaking.

At that point I realized - I need to learn who my users are, what their goals are, and how my software is going to help them.

I started to learn their business.  I put myself into their shoes, created user personas - and stories for those personas.  I wasn’t going to make the same mistake again.  From that point on, instead of focusing first on the technology, I started to approach my development tasks from their perspective.  The result is the products I’ve worked on have gotten better.  They are more widely used - and they are more effective in helping people.

Tying this a bit back to some of the topics we’ve just touched on - your users are not always going to know exactly what they want at the outset of a project (or even a sprint).  Let them know that it’s OK to change their mind later if things don’t turn out like they hoped.  The most important thing is that they come out of the project with software that will help them - and they’ll enjoy using.

I Believe... automated unit testing is a must

Automated testing is something I take for granted as commonplace - but I know it’s not - and I don’t understand why.  I hate the tediousness and monotony of testing so much that this is something I’ve done my whole career - long before I was ever introduced to JUnit.  Even more than I hate the tediousness and monotony of testing though, I hate the shame I feel when some code I delivered doesn’t work - especially if the code worked in a previous release.  I’ll do whatever I can to avoid that feeling.

The benefits of unit testing are (in my opinion) so well documented, that I won’t go into too much detail, but I did want to touch on some of what I consider as the high points:
  • Automated tests are the best way to ensure that new changes don’t break other (seemingly unrelated) parts of the application.  They give you the confidence to make changes, refactor, and move the code forward.
  • Unit tests are the most reliable form of documentation.  They give the best account of how the code behaves - today.  Design documentation might give a good idea for what some code did when it was released - but it’s often not updated to reflect changes, bug fixes, or adjustments in scope.  The tests are the best and most reliable place to get that information.
  • Interestingly, going into a software development task thinking about “how am I going to test this”, is a great aid to software design since creating code that is easily testable often leads to loosely coupled modules.  Test Driven Development (TDD) is a powerful approach to unit testing because you not only gain this aid to design, but you have a great indicator to signify when you are done coding.

I Believe... loosely coupled software is the best

Loosely coupled software means that dependencies between classes and modules are limited as much as possible.  It also means that when inevitable dependencies do exist, these dependencies are abstracted through an interface.  Why is it so important?
  • Loose coupling helps to keep your code flexible - it’s easy to swap in different implementations of an interface - or swap back if things don’t work out.  It makes it easy to adapt to change.
  • It allows more control over testing. Fewer dependencies allow you to more effectively write focused tests.  Having mock implementations to abstract database dependencies is a huge aid in testing since you don’t need to load complex test cases into the database.
To help achieve writing loosely coupled software, I rely heavily on dependency injection - and specifically Spring.  Dependency injection helps to enforce the loosely coupled software design practices of coding to an interface and limiting dependencies.  Dependency injection prevents me from getting lazy in following loosely coupled design practices.

I Believe... loosely coupled architecture is the best

Just like software - but maybe even more important - I believe loosely coupled architectures are the best.  Here’s what I consider a loosely coupled architecture - and it looks an awful lot like the Model-View-Presenter (MVP) design pattern.

First there’s an interface (the view).  This is the component your users will use to interact with your system.  Ideally, there’s not a lot of logic here - less logic means fewer unit tests.  The view can be a client-side user interface (like Flex or GWT), a web service, or API.  For web service views, I prefer REST as I think it is the most flexible and easiest to test.

The presenter is where any business logic exists.  It’s the core of your application.  It processes data from the model and passes it to the view.  The presenter is the place where following loosely coupled software design is the most important and where a lot of the dependency injection occurs.  Most of your unit tests will be written against the presenter code.

The model is an interface to your data.  This can be a module to access traditional database or a long latency DB (like a call to a web service).  Again - there’s not a lot of logic here so - like the view - you won’t need a ton of unit tests here.  They are also easy to mock out while developing the presenter or during testing.

Learning GWT was where I was formally introduced to the MVP design pattern.  MVP allowed for a level of freedom in testing UI components which I’ve never experienced before - mostly because it removed some of the dependencies from traditional MVC designs.  Now I was able to mock out either the view or the model - or both - which provided a great amount of flexibility in developing, experimenting, and testing my code.

But it also got me thinking - what if I wanted to swap my GWT view to something else (like to a native phone app).  No problem!  I could change the UI without affecting the rest of the system.  I could even support multiple user interfaces and provide tailored experiences based on device, user preference, location, etc.

What if I wanted to test out a NoSQL implementation of my data store.  Piece of cake!  In fact, I could run both options side by side or only convert a portion of the data store to NoSQL if I wanted.  The presenter wouldn’t even know (or care) as long as the interface to the model is sufficiently abstracted away.

We’ve already talked about the benefits of testing mocked out versions of these systems.  They still apply. 

These are the systems we should strive to build!  There are a lot of big benefits to following a loosely coupled architecture approach like this.  They are inherently flexible and immensely testable.  Our users and the business will love how easily we’ll be able to react to changes, seemingly anticipate their needs, and quickly respond to changing trends.

I Believe... using tools help us reliably move faster

Like many other tasks - writing software is a lot easier if you have the right set of tools - and you know how to use them.  Here’s a short list of tools I believe all software teams should be using:  
  • IDE - I like eclipse, but a case could be made for any of the great IDEs out there.  A good IDE eases the process of refactoring.  It’s a great aid in researching code - providing detailed usage information on classes and methods.  An IDE will alert you of syntax errors as you type - and rebuild the application on save.  The integrated IDE debugger allows you to easily step through your code and inspect variables when you experience tough problems.  I know a lot of people who are may look at developing in text editors as a “badge of honor” because it’s “old school” - I think they’re mistaken.  I was forced to develop in text editors early in my career and I can’t imagine going back.  I’m much more productive now.
  • Automated Builds - There needs to be an automated way to build projects from source control with minimal effort - ideally without loading the project into an IDE or creating a test database instance.  Like many of the other things we’ve discussed already - if you can limit the number of dependencies needed to build a project, the greater success rate (and less pain) new team members will experience in joining the team.  Overall - your project should also be more stable if the build is stable.  I used to use Ant for this (and sometimes still do), but I much prefer Maven because Maven will also manage dependant libraries your project uses - and the versions of those libraries.  With Ant you need to figure a way to manage these yourself - often by including them in source control which can be a pain if many projects use the same utility libraries.
  • Source Control - Oddly, I’ve encountered more than one organization who doesn’t use source control.  One even stated that they abandoned source control to keep them “process light” and more Agile.  In fact, they still had a source control process in place but they were doing it manually.  Like the text editor point, this isn’t “old school” or “light” in anything - other than common sense.  There are several great (and proven) tools to automate this task for you - use them.  I’ve used CVS and Subversion extensively and I’d recommend either.  I don’t have any experience with distributed version control systems, but I’m looking for the right team and project to try one out on.  I can really see the benefits to a system like that.
  • Bug Databases - Similar to source control - you’re going to do this anyway, you might as well use a tool to help manage your bugs and other development tasks.  I like Bugzilla.  The user interface leaves a bit to be desired, but it gets the job done.
  • Wikis for Documentation - For a long time, I created documentation in Word and stored them in a shared folder.  I had a few problems with this
    • they are hard to search for content
    • it’s hard to link between documents
    • it’s hard to coordinate multiple edits in the same document
    Enter wikis.  A wiki addresses all of these issues and with the combination a WYSIWYG editor and simple markdown it’s not hard to produce great looking documents.  I’ve used and maintained a wiki for my development teams for a long time.  I've had so much success in doing this, that it’s not something I think about much anymore - I just do it.
  • Automated Testing Frameworks - I’ve already talked a lot about automated testing and the benefits automated tests provide to development.  I don’t have much else to say on the subject.  I use JUnit and I’ve been writing more and more of my user stories in the Given->When->Then format popular with BDD tools.  I hope to get to the point where I'm using some of these tools soon.

I Believe... software is a craft

Like many other skills - woodworking, cooking, playing an instrument, writing - you need to constantly practice to get better.  As you practice, you’ll learn subtle tricks to help you to work efficiently while gaining valuable experience in solving more difficult problems.  It’s hard work.  You need to be committed to your practice and to improving your skills.  I continually look for new skills to explore and add to my programming repertoire.  It might seem counterintuitive at first, but learning Ruby a while back immensely helped to expand my Java testing and architecture skills. It gave me a new perspective on software development.  Many people participate in code katas as a way to focus their practice time.  However you do it - constant practice is a telltale sign of a programing craftsman. 

Sharing your ideas - and learning from others - is another way to expand your horizons. In addition to your practice time - you should set aside time each day to read books or blogs.  I listen to technical podcasts during my commute and my time at the gym.  In earlier times, journeymen would work under several master craftsman to learn different ways of doing things.  The concept here isn’t much different.  There are a lot of smart people out there who are willing to share their experiences and tell you what’s working for them.  For your own good, take advantage of these resources.

I Believe... it’s important to love what you do

Because it takes so much time and effort to follow the recommendations that I believe in - it’s very important that you love what you do.  You need to be passionate about your job.  If the most important things to you are a paycheck or time off - you might not be in it for the right reasons.  I do believe, however, that if you are passionate about what you do - the money will find you.

A few weeks back, my daughter wanted to have a lemonade stand.  It was hot and she said. “it’s a good day to make some money!”.  She was spending a lot of time trying to figure out what to charge for her glasses of lemonade.  I asked her to think about it differently - that if she focused on creating the best glass of lemonade she could - the coldest, service with a smile, etc - the money would take care of itself.  Creating the best glass of lemonade was where her focus should be - not on the price.  People would remember how good the lemonade was- maybe they'd tell other people in our neighborhood  - and they’d probably be happy to stop again.

You need to do some self-exploration to find what you’re passionate about, how hard you’re willing to work to reach your goals, and what you believe in.   Programming is my lemonade - and I work hard to deliver as much value though my work as possible.

I love being a programmer.

I love delivering tools that help people and businesses work more efficiently.

I love to create and learn.

I love mentoring and helping others to improve their skills.

Love what you do - and work hard.  Your passion will show through in your work and you’ll be amazed at what you can accomplish!

Comments

Popular posts from this blog

FRail :include

Cognitive Dissonance?