Once again, I have moved. This time it is for good, as I have purchased my own domain. You can now find me at http://www.DontForgetYourTODOs.com/.
I can’t help it. I read Steve’s post too big to fail on brip blap and I immediately apply its principle to life as a developer. The focus is about breaking down “too big to fail” life events into smaller more manageable components that are less likely to wreak havoc.
How is this relevant to anything in the world of software development?
1. System Design
When designing systems, separate components by logic functionality. Systems that are responsible for continuous database queries, should not be tied to a web site that serves content, such as in Simulate a Windows Service using ASP.NET. While this idea may be good in theory and for any shared hosting environment when you can’t install or run services on the server, the potential that a deadlock or frozen thread occurs will increase. If that occurs, you can kiss all of your active user sessions goodbye.
2. Application Design
Separate application logic out so that when one component gets changed, it doesn’t force a complete rewrite. Websites and web services should not tie directly to the data layer. Design N-layer systems (read the differences between N-Tier and N-Layer applications) so that there are no direct dependencies on lower-level technologies being used.
Maintainability in separate components increases as the number of layers does. Take this in moderation though, too much loose-coupling in your layers, leads to overkill and needless complexity.
3. Class Design
When designing classes, follow the Single Responsibility Principle (SRP) of the S.O.L.I.D Class Design Principles. If your class has more than one reason to change, then it may be “too big to fail”. The below example helps:
The above breaks the SRP because any minor change required to one of the three purposes of this class causes the whole class to change:
- The process to calculate the tax rate of the employee
- Database Schema that matches to the Worker
- Employee Id that is used. SSN today, numeric number tomorrow
Any single change impacts the class which is responsible for three very different purposes. While this is not “too big to fail”, the class is “too big for its own good”.
Have you ever heard a non-technical computer say that they are having computer problems whether it be viruses, pop-up
porn ads, slowdowns, or network problems? Often they do not know where it came from. Hearing this have you immediately thought, “I never have any of those types of problems. This person must just not know how to use their computer.”?
As developers we don’t have these problems because we understand how a computer should work. We know what will get us into trouble and can easily identify warning signs. We also troubleshoot ourselves out of situations. In short, regardless of how usable the system, mentally we understand what needs to be done to get what we need.
Is this how it should work? Certainly not. We cannot take users for granted, hoping that they understand how to use our application. A user interface should handle system and application commands that a user wishes to run. If our users knew they had to call process A, click button B five times, and cache the response before the desired result would occur, there would be no need for usability (or us). Users would be smarter, and perfectly capable of troubleshooting their own bugs.
Such a perfect world does not exist and it is our responsibility to ensure that the software we release to our users doesn’t have any potential holes or pesky bugs in it. We must focus on making our applications more user friendly so that it is obvious when they perform an action that endangers their computer, or that those actions never occur in the first place. As developers how do we do that?
So what can be done? Do we preach that usability testing is necessary before production? No. That music falls on deaf ears. Besides, who wants to give up valuable project time or money to test an application that is already behind? Even when usability testing is scheduled and performed, there is such a short amount of time left in the development schedule to fix any recommended changes.
My recommendation is that usability testing should come as an iterative and cyclical process throughout the development life cycle. It should not be considered usability, but instead usability development. Team members should be aware of it from the point requirements are defined to the point that the final piece of code is written.
This should be done by pushing the below responsibilities onto all team members:
- Do not let anyone test their own code for the final round of testing
- Concentrate on understanding the needs of users early
- Perform early and continuous testing. This can be done through peer developer testing or lead developer testing core functionality
Do you know what is potentially worse than hard coding values into your source? Soft coding. Why? First a definition:
Soft coding is the act of writing code so that it depends on external settings such that behavior may change without updating the source.
The reason we hard code is because we
are lazy and don’t know any better expect that given conditions will never change. Soft coding is born out of opposite reasons. Soft coding is intended to accommodates business rule units subject to change so that application modifications can occur without forcing code pushes or deployments. Soft coding is often seen in the form of configuration files.
Used cautiously soft coding can provide ways to make code become dynamic (switching logging formats, web service URLs, using reflection to create different business objects, etc.). When used in excess, soft coding complicates code by over-abstraction and develops into an anti-pattern.
Below are a few of the pitfalls that I’ve run into with soft coding:
- Increase of complexity: Developing dynamic code based on configuration values is essentially equal to writing another new language. The problem here is that we try to account for every possible scenario by making the code capable of doing things that will never be done. This results in spaghetti code and it just gets messy.
- Development complications: Code is written in an IDE because it can interpret the grammar and check for syntactical errors. Debugging is a breeze
in most cases. Again, we are writing a new language and the problem is that we often don’t put as much time and effort into this portion of it. A lot of room is left open for loopholes and unaccounted conditions, while increasing the possibility that an unexpected exception will occur.
- End-user error: MY opinion is that this is a big issue for CMS sites. Developers spend lots of time building out the site, making it template based, and hand it over. The new owners then proceed to make content changes that bring the site to its knees.
The better your software is when produced, the less customization it will really need and the less users will find that they wish to change it.
Do you focus on the details necessary to complete a task, or do you dwell on end results and overlook implementation details needed to achieve? Are you big picture or little picture?
I believe that the big picture people will inevitably rise above the smaller more detail-oriented picture people. This view does not state that the little picture people will fall off the face of the earth as the big picture people rise to power, but instead represents it as a yin-yang relationship in which one cannot be successful without the other.
This analogy can apply to almost anywhere, but for now put it in perspective of people trying to determine their career path, specifically in the technology industry. At this point in my life I am an impressionable, eager developer, faced with a difficult decision:
Should I become a Technology Specialist or a Jack of All Trades?
Do I want to put forth all my efforts into a specific product or do I want to step back a level and just understand a little about it and let the experts take care of all the nitty-gritty details?
I choose this example because I cannot see a path that says one of these is better than the other. I believe the decision to be made is a decision that no one can make but you. As a developer are you really interested in being an e-commerce, AJAX, or CMS “go-to” guy? Or, are you more interested in understanding most of the strong (and weak) points of many different product lines and knowing enough to be dangerous in any scenario?
Employers have use for both types of people. There is a time and a place. When business is booming and there is money to throw at the problem, bring in the specialist (and pay more). They are the sharpest tool in the shed and the one who will crank out the quality solution as fast as possible. Reverse that situation and do some budget cuts, lay off employees, and we find that a company can’t afford to pay as many specialists. They can pay our jack of all trades the salary of one person, and pile on the workload (of many people) for the same price. Do you see the trade-off?
I’ve made my decision. Up until a few months ago, I wanted to be a jack of all trades until I realized that choice lacked some opportunities available only to specialists. After further thought, I have settled on jack of all trades master of some. As to what that “master of some” will be, I do not yet know. Time will determine that.
On another note, this may be going against the other author’s post, but I believe that we must all show a bit more humility and acknowledge that even though we think we are big picture there is always a bigger fish in the sea that is more bigger picture and depends on us to implement the details.
During times like these, why should I give up my responsibilities and throw away any job security that I have?
Job security should not be because you are the only one capable of performing fixer-upper tasks or upgrading a legacy system.
Job security should mean the company views you as an irreplaceable asset. If job security were based on your responsibility of maintaing an application or system, how are you ever able to grow and take on new projects?
As a consultant, I ended up in this scenario because the responsibility of the developed system was left completely in the hands of contractors. Any full time employees who were previously involved left the company. When I was the last contractor on the project and ready to start another gig, upper management discovered that there were no internal developers with knowledge of the system that was built. I became irreplaceable, but not because of my abilities. I and the upper management team failed to ensure that other developers understood the system. No one had the confidence that they would be able to maintain it should something go wrong. As a result, this hurt me by preventing me to take on additional work opportunities and start on other projects.
Unfortunately we cannot always depend on management to take care of spreading knowledge around to other teams as that requires more resources to schedule on their part. The key here is spreading the knowledge by taking initiative. Invite other developers, junior ones specifically, in to your circle and educate. Question them and teach them. Tell them you are doing this so
you can move on they gain a more well-rounded view of different application designs and roles. Make it sound interesting. Don’t pass on what you did right about the system. Pass on what is wrong with the system and what you would have done different so that they learn from your mistakes.
Elaborating a bit more on my last post on dealing with poorly designed applications, as developers we often find ourselves in sticky situations where it consumes more time to fix something that should take little to no effort at all. I will be the first to admit that I have caused my own fair share of these problems.
Below are some of the most trivial solutions that I’ve collected from my own experience and samples that I’ve read. These can be fixed by better development and coding standards:
1. Over Designing
Ever meet someone too smart for their own good? There is a fine line that smart people often cross when writing code. Once this line is crossed, the code they produce becomes an inversion of their intelligence. You can identify this when they constantly refactor code that you’ve written to be more efficient, dynamic, generic, and re-usable. I’ve seen developers try to make .NET generics generic.
Please do not invent something that will synergize the evolution of social networking when all you need to do is build a blog. Yes, some things are prone to change (content, configuration variables) so don’t hard code those. At the same time, if your team is the only one using the application and are expected to maintain it, then make the solution straight-forward and simple. They will thank you after they make an emergency fix.
2. Code Complexity
Nothing can be worse than a lack of unit tests when making modifications or upgrades to someone else’s code. With poorly written code, it is difficult to determine if the change being made will break anything or not. Even worse, is the change that has to take place in the spaghetti function that has 800 lines of code in it. One line gets changed and it seems as though you just witnessed the program in self-destruct mode.
Maybe an analogy will help here:
If I were asked to find my keys in my own house, I would have an idea where to look. The kitchen, the bowl by the front door, etc.. This is because it is my house and I am most familiar with it. Now imagine I asked you to find some keys in my house. Where would you start? Would you start looking for a utility bowl that said “keys” on it, would you look in drawers throughout the kitchen, pockets in a coat?
Sometimes our code closets are left in a state of disarray for someone else to take care of. When they need to change something, do they know where to look? Is your code clean and self-descriptive so that they can easily understand what each function does to prevent a change in the wrong place?
3. Over Commenting
As a student going through school, we were taught to comment our code. I was told to provide pre-conditions and post-conditions as well as a summary and a description of every parameter to all public/private/internal methods. You’ve seen it happen and I’ve seen it happen, another developer (or yourself) comes along and makes changes to the way the code works, adds a variable or a parameter or two, and then doesn’t update the comments. At that point our entire easy code universe is out of sync.
What about saving yourself the time and instead of writing code that requires comments to explain how it works, you write code that is completely legible and flows together so that it requires no additional comments? Take a look at this snippet that I grabbed from Jeff Atwood’s Coding Without Comments and you’ll be able to see what I mean.
becomes this with a comment:
and can be simplified to this:
See how much easier it is to understand? I don’t have to understand that
that the complex code calculates a square root since the method name explicitly states it.
Having said these points, there are many things that you can do to simplify code and make it more developer friendly. Be careful not to waste too much time breaking code down and finding re-usable solutions. I’ve walked my self into many a corner trying to come up with creative ways from having to write a ton of GUI code and handle dynamic layouts. Just keep it simple and the code will speak for itself.
Do you have any tips for keeping code simple and straight to the point?
How do you feel about the way that our developers that come straight out of school code? Are they taught properly?