State of Software Development
Hello. I felt moved to blog today. To address the state of software development. To address how software developers view software development. It seems that software development, as of recent in my own experience, has become this method of making money fast, removing art from something that offers so much creativity. I personally do not do this because I can make money from it. There are soo many respected fields in our world today that bring new art to everyone. They teach and tell us as human beings that things are going to be ok. That anything is solveable and possible. That this world, although engulfed in soo much pain and suffering, can give us something that we forever be etched in our minds for generations to come.
That’s how I feel about software development. It’s not something that I do because I can earn a decent, honest living from it. But it allows me to bring something to consumers in ways that can seem unimaginable. I believe Jon Skeet said it best that doing something because you live for it, driven to do it, even if for free, truly defines that persons love for it. In so many words.
After working for many companies and observing the pattern of software development they adapt, it seems that the main focus is to make money. But what about the consumer that buys it? I expect that when I purchase anything in life, even the simplest of things, that I will get what I pay for and enjoy it to its fullest and share it with my friends and family to enjoy as well. Do people feel this way about software? Better yet, do software developers feel this way about something they spend most of their waking hours being involved in. This is what I feel about software development. Although this sounds like some prologue for a book, this is a book that never stops writing itself. It is an idea that all “good” developers must believe in whenever they write a piece of code. The money aspect of software development allows me to continue to create art. Nothing more than that. No different from publishers investing in an author. Or a producer investing in a film.
I am a big believer of if you decide to do something in life, no matter what it is, you try to be your best at it. If I am a surgeon, will I not try to be the best surgeon? Lives are at stake. User experience is at stake. For generations and generations. If I am a middle school teacher, don’t I want to do my best to be the best at what I do? To find the art. To find the creativity behind it. I still remember my 6th grade teacher, seriously. Because that is how she taught. And if I ever have children, I want them to experience what I experienced.
Well, if I develop software, why not give the consumer that experience? To feel that no matter what, this developer is going to give his all to give me something to remember for generations to come. And I will pay anything to get that because it is priceless.
I have worked with soo many developers that are driven because they have a family to support. I use to be that way when I was married. Nothing meant more to me than that feeling of proudness when I brought home the check every two weeks. But I showed no enthusiasm behind what I did for a living. I had no enthusiasm for what I did. While growing up I was always creative. When I was married creativity took second place to bills and everything else. Then after I was divorced, I said to myself that I will only focus on things that I can control in life. Going from one extreme to the next is never good. But I did that. And that left me with creativity and art. But no family to share it with. Anyways, my point is, if I had to talk to those developers that just “put bread on the table”, I would tell them to be proud of what they do everyday and share it with their family and friends. Help grow new artist. Help develop a new respectable career.
Why? Because the state of software development seems to be engulfed and measured by dollars and cents. Thus, removing fun, love, creativity, and art from something that is full of fun, love, creativity and art.
!= null
Ok. I am try to figure out the validity behind writing “!= null” in code. It seems to me that this is pointless to use and redirects the real issue in application code as well as being misleading for the user. Note the following example,
I am seeing way too many teams on my project doing this. In my opinion, this is pointless. So where does this leave me as a user? I am allowed to click Save for a device and basically nothing will happen.
If the Device object is not initialized for whatever reason, it should be handled somewhere else, like when I fetch the persisted Device object to update or when I initialize a new Device object on creation. But I do not, as a user, want to discover that after I spend precious minutes filling in a view with device information, only to find that it hasn’t persisted when I click Save.
If I initialize a Device object on load and for whatever reason, the fetch methods do not return that Device object, as a developer, and as a user, that is when I wish to know that a problem exist. If I initialize a brand new Device object with its defaults on load and for whatever reason, the initialization default device methods do not return the valid Device object, as a developer, and as a user, that is when I wish to know that a problem exist.
Anyways, this code is something I inherited today. And there are 2000 line view models that I must refactor. I do not think that this is a moot point and is something valid. If I get a defect that a user can’t successfully save a device, then I will undoubtedly start debugging and testing in the wrong area. The real issue is redirecting itself because of poor coding which will increase technical debt simply because I spent more time to solve the problem.
Proactive Solutions for Preventing Recurring Defects In A Software Projects
The beginning of good testable code
The beginning of good testable code is having a product you believe in, strong domain knowledge, good user stories to support it, and a strict AGILE process. User stories should be clear and should fully satisfy the needs of the product owner and should be easy to understand by both business analysis and developers.
A user story should not simply read User Entry Screen without any business rules or test cases. As a developer, this is not enough to test and implement. Somewhere in the product owner’s vision, they may see it working one way. It is not the developer’s responsibility to interpret this. It should be as clear and as precise as possible. As a consumer, I will never walk into a department store and ask the clerk for a shirt. The clerk may interpret that as a red sweater when I really wanted a blue polo.
There are questions that need to be answered that will allow a developer to begin testing and implementing. For example, what type of information is needed to enter a user? What are the required fields and what is not? What validations are needed? These are basic questions for any requirements and depending on the domain, more questions will arise. Most of this information should be answered by the business analyst and domain experts. It should be included in the user story before it makes it across a developer’s or quality assurance’s desk. Sprint planning meetings are designed to fill in any blanks developers may have that could potentially impede development. That details discovered from these meetings becomes true requirements, business rules and then test cases for both developers and quality assurance. The developer takes these details and starts testing and implementing.
In AGILE development, we should follow INVEST[i] for creating user stories. User stories must be Independent, Negotiable, Valuable, Estimable, Small, and Testable. The points I stress are Independent, Small, and Testable. Developers should never be blocked by other developer’s. By having user stories that are actually business rules result in dependant user stories and make it impossible to write testable code effectively. Developers having user stories that are not dependant on other user stories allows them to write code without dependencies.
Test cases should follow single responsibility. This helps tremendously with writing unit test and implementation. Developers are held accountable for delivering quality code. Single responsibility[ii] is one of those principles that good developers follow to achieve this. If user stories have single responsibility, then it is easy for the developer to write single responsibility code. For example, creating a new patient and deleting an existing patient should not reside in the same user story.
Test-driven development as an option[iii]
This is optional and for informational purposes only to help the reader understand that it is not an option to follow this process at the current stage of development.
Test-driven development is design and implementation processes by which the developer begins the development of a user story starting with a test or series or test that represent test cases provided in user stories. Adopting a test-driven approach is a practice in designing software that is testable. It is best to adopt this process at the start of an AGILE project. It is not necessary to follow test-driven development to write testable code. It is simply a process of designing testable software.
- Developer gets a user story.
- Developer writes a unit test for some test case from the user story.
- Developer runs unit test to verify test case initially fails.
- Developer writes implementation for the test case that is being tested.
- Developer runs unit test.
- Unit test case passes.
- Refactoring if necessarily.
- Check for code duplication and refactoring again if necessary.
- Confirm that unit test gets executed as part of the continuous integration process.
- Move on to the next test case until user story is complete.
Developer testing methods
Below are lists of testing types that are essential for developing any software.
- Unit testing[iv]
- The purpose of unit test is to test a small unit of code. Developers need to understand the difference between unit test and integration test. If a developer is writing let’s say, a calculator program, and wants to test the multiplication of two numbers, then said developer will test that and only that. If a developer is writing an orders program and wants to test the inputting of an order, validate the order, validate payment, validate buyer, calculate shipping and taxes, send the order, and send the confirmation with tracking information for that order, then he writes an integration test. Unit test should always test one thing. If you find that you are testing multiple things in a single test, you are violating the single responsibility principle and probably have test cases that are too large. If you have more than one reason to change test or implementation, then you violate the single responsibility principle.
- Mock integrated testing[v]
- The purpose of mock integration test is to test a specific layer that could interface with other layers we do not wish to test. Now here is where mocking comes into play. The developer does not wish to test the interfacing layers. The system under test should be the specific layer the developer is currently writing code for, not every layer that it interfaces with. For example, the developer wants to test validation before he performs a save via a repository create method. If it is successful, then the save happens, right? With end-to-end integration testing, sure it does, but when the developer is writing a mock integration test, he wants to verify that the repository create gets invoked after validation is successful but does not wish to actually invoke it. He expects it, but no action is taken. This is best known as a behavioral verification test. Anything else implies that the tester will be saving the object after the validation was successful to the database. And that is what persistence test are for.
- Mock integrated testing is not as straightforward as it may sound and requires some help. It will always require some test isolation tool, such as RhinoMocks. Programming to interfaces, not implementations, allows the developer to mock objects based on that interface. You can stub out implementation if you like, however, this does not allow for expecting when things happen, how many times it happens and in what sequential order. Stubbing only allows developers to alter the implementation.
- Mock integrated testing will also sometimes require some inversion of control[vi] container, such as Unity. Removing hidden dependencies may seem like a lot of work but if you take pride in the quality of your software, you will at least consider it. Removing hidden dependencies becomes important while writing testable code. Injecting dependencies into our system under test via constructor injection allows us to mock out the dependencies before we instantiate that system under test.
- Persistence testing.
- The purpose of persistence test is to test repository CRUD[vii] functionality. This is the last stop before the developer interacts with his database of choice. Persistence are important because they test for any changes in database objects such as table column definitions, stored procedure parameters, or stored procedure and view result sets. Persistence can be the most involved test to setup because it involves the building up and tearing down of test data in your database. These are also the longest running of all tests due to having to make hits to the database.
- Create persistence test – Requires seeding of any foreign key relationship tables, for example, lookup tables, within the set up fixture. The tester will verify that the object was persisted. After verification, the primary table and all foreign tables are truncated in the tear down fixture.
- Read persistence test – Requires seeding of primary and any foreign key relationship tables within the set up fixture. The tester will verify that the object was initialized with the persisted data. After verification, the primary and foreign tables are truncated in the tear down fixture.
- Update persistence test – Requires seeding of primary and any foreign key relationship tables within the set up fixture. The tester will verify that the object was updated and persisted. After verification, the primary and foreign tables are truncated in the tear down fixture.
- Delete persistence test – Requires seeding of primary and any foreign key relationship tables within the set up fixture. The tester will verify that object was removed from the database. After verification, the primary and foreign tables are truncated in the tear down fixture.
- Automated acceptance testing[viii]
- The purpose of automated acceptance test is to give the developer more end-to-end integration, black-box, test coverage. This is more or less feature driven testing and is defined can be defined by users. This can introduce domain-specific languages, like Gherkin syntax, where plain language statements about the behavior of the feature are converted to code. This methodology is also widely used with behavior driven development[ix] but can be adopted in pretty much any process. This also serves as an automated regression tool that proves useful to quality assurance.
- The purpose of persistence test is to test repository CRUD[vii] functionality. This is the last stop before the developer interacts with his database of choice. Persistence are important because they test for any changes in database objects such as table column definitions, stored procedure parameters, or stored procedure and view result sets. Persistence can be the most involved test to setup because it involves the building up and tearing down of test data in your database. These are also the longest running of all tests due to having to make hits to the database.
Automated build process
Currently using Team Foundation Server for the automated build process.
Making the automated build self-testing with Continuous Integration[x]
Once the code is built, all tests should run to confirm that it behaves as the developers expect it to behave. Currently, we verify if the code builds successfully. This is simply not enough.
When unit tests fail or a bug emerges, the build can revert codebase back to a bug-free state, without wasting time debugging. The developers detect and fix integration problems continuously – avoiding last-minute chaos at release dates. The developer receives an early warning of broken and incompatible code. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Read through the follow scenario and later you will see how making the build self-testing improves in development:
- Team A makes a code change to the signature of their cross module service.
- Team B had a feature that consumes cross module service two sprints prior that was certified by quality assurance.
- Team A does not notify Team B of the code change to the signature of the cross module service.
- Team A will check in the code change.
- The build kicks off and is successful. Code is built just fine.
- Quality assurance does regression and gets a nasty exception when the code calls the cross module service.
- Quality assurance then proceeds to create a defect.
- Team B gets the defect and has no idea why this is broken or how to fix the defect.
- Team B confronts Team A and now Team A makes them aware of the code change.
- Team B makes the suggested change to their code to match the cross module service signature.
- Team B checks in the code change.
- The build kicks off and is successful. Code is built just fine.
- Quality assurance does regression and are pleased that said feature works as intended.
How is this productive? Every time Team B makes a change and do notify the consumer, Team B gets a defect. How can we fix this? We can simply add test to the code build and continuous integration process.
- Team A makes a code change to the signature of their code module service.
- Team B has a test that consumes Team A’s cross module service.
- Team A does not notify Team B of the code change to the signature of the cross module service.
- Team A will check in the code change.
- The build kicks off and test fails because they are part of the continuous integration process. Code is not built.
- The developers are notified and the code changes to the signature are made to fix defect.
- The build kicks off and test pass. Code is built just fine.
- Quality assurance does regression and are pleased that said feature works as intended.
Persistence tests usually take a long period of time to run. So it will not be productive in some cases to run these test as part of your continuous integration process like gated check-ins. However, there are tools, such as CruiseControl[xi] and TeamCity[xii], which allows local test execution on TFS check-ins.
Developer testing should always be used with your continuous integration process. It is very important. Without it, the developer’s test is almost useless. Why? Developers are not psychic. They do not always know when changes to code are happening to execute their test.
Coverage
- Code Coverage
- How many lines are executed, how many times expressions, branches executed. How viable is Code Coverage?
- Feature Coverage
- The determination of how much functionality of the design has been exercised by the verification environment. What features have test around it?
Process for testing defects
- The process for testing defects follows closely with test-driven development, if the developer’s code is testable.
- Developer gets a defect.
- Developer writes a test for the implementation where the defect exists.
- Developer runs test to verify the defect.
- Developer makes code changes to the implementation to fix defect.
- Developer runs test again.
- Test passes.
- Refactoring.
- Check for code duplication. Repeats refactoring until satisfied.
- Confirm that test gets executed as part of the continuous integration process.
- Move on to the next defect.
- This prevents recurring defects because if a developer makes changes to the implementation that fixed the defect, the test will fail. And because it is part of the continuous integration process, the build fails.
Overall lack of encapsulation on business objects
We have business objects that have behavior that is not explicit enough. For example, a developer from Team A wishes to consume patient business objects, which belongs to Team B, in order to delete that patient’s insurance. The developer from Team A currently, cannot simply invoke a method in that patient business object to delete it, like Patient.RemoveInsurance(patientInsuranceId);. Currently, the developer from Team A needs to get a list of insurance enrollments for the patient, find the patient’s insurance he wishes to delete, remove that patient’s insurance from the list, then save the list of patient’s insurance. Any team that wishes to perform this action has to know way too much about the implementation of Patient. If another developer, from Team C wishes to consume this also, guess what? He would have to get a list of insurances for the patient, find the patient’s insurance he wishes to delete, remove that patient’s insurance from the list, then save the list of patient’s insurances. If the owning development team for Patient, Team B, wishes to change how patient insurances are removed, guess what? Team A and C would have to change their implementations. If consuming teams are not aware of this change, more defects will occur. This should be hidden to developers that wish to consume it. The inner workings should be encapsulated by the team that owns Patient.
[iii] http://www.threeriversinstitute.org/blog/ (Kent Beck)
http://www.testdriven.net/ (MVS Unit testing add-in)
[vii] In computer programming, Create, Read, Update and Delete (CRUD) are the four basic functions of persistent storage.
Copy and Paste Coders
I am going to quote from Jon Skeets book, C# in Depth.
“There are two kinds of pianists.
There are some who play not because they enjoy it, but because their parents force them to take lessons.”
97% of developers fit pianists #2 and don’t care enough about what they write to actually understand what they write.
There are some things I can close my eyes to when reviewing a peer developers code. But when it comes to unit testing, I can’t be shut up enough about it. Why? Because there are usually no metrics put in place for unit test. What does that mean exactly? Developers are not held accountable for the number (or quality) of unit test he or she writes or lack there of. So if you don’t have to write them, then don’t. Unless you are me of course. Because I love doing it and I can’t seem to write enough of them and I can still push out the same amount of story points a sprint if I wanted to.
Anyways, managers had an “agenda” to hold developers accountable for testable, quality code. This was a fad that quickly went away after a sprint or two of developers whining. So during that phase, some developers, like the code they write, copy and pasted my FREAKING unit test. Now I ensure I have state and behavioral verification test. I use tools like RhinoMocks and NBuilder. Below is a test a developer copied from one of my test and pasted into his and obviously changed the system under test.
What the hell man that was copied from this???
They can’t even copy and paste correctly. Why copy something you don’t fully understand and just to please management. The one level of the organizational structure that should not care if a developer writes test or not. But the truth is that managers and QA testers don’t know a damn thing about unit test and all the philosophies that fall under it. So when a developer is showing a passing test for screenshot #1, his metrics is looking pretty damn awesome. I would have more respect if they just wrote Assert.IsTrue(true);
To write test to satisfy management is Phail in my book. Developers should WANT to be accountable for the quality of the code they write. But most don’t. So I get labeled as being “difficult” because I stand up for what I believe in and refuse to back down. But that makes me the “worse developer” ever.
Mobile Development
This weekend is dedicated to mobile development. When I bought my iPhone way back when, I bought a MacBook Pro, an iPhone development book, and downloaded the SDK. That was months ago. This weekend I will actually jump into it. It’s still part of my goal to be more polyglot. I will jump on Ruby again at some point to pick up where I left off but for this weekend. The dedication goes to mystery behind iPhone development while I sort out which Netflix que to watch while I do it.
My main focus is this. Can I practice the main OOP principles and philosophies in mobile development? More to come. Sit tight.
“Phail Developerland” – My Movie of the Weekend
While going into the weekend, there is a little movie called “Zombieland”. Go get it now if you haven’t seen it and if you did, see it again. This movie is just plain awesome in my book. I have seen this movie before. This is nothing new. But I just love it and it never gets old. Why? Because I just simply replace all the “zombies” with “phail developers” and my imagination just runs wild. My best Woody Harrelson flick by far (besides Natural Born Killers of course). Favorite quote as I replace “zombie” with “phail developer”.
“It was really fun and really cathartic. You get through the end of the day, you’ve killed a couple hundred phail developers, you feel like you’ve accomplished something.”
“Some are moving slow, but they’ve all got weird kinks as they walk. I don’t really know who they’re supposed to be, but in this one, they didn’t seem to be moving too fast. It makes them easy targets. The best phail developer kill was the one with the chainsaw. You turn the thing on and you just search for the big arteries.” – Tallahassee
Please go watch this if you are not sensitive to gore.
After I get my fill of this movie, going to watch the Ringu Trilogy (the none lame Japanese original) again and back to Ruby. Cheers. Good weekend all.
Ruby Unit testing, Part 1
So I have a class, Person.rb and I want to test the method changelastnametosucka
The test would look something like this:
I will be breaking this up in the next blog entry but for now, just keep a few things in mind.
- Creating a class.
- Mutators and accessors methods
- require
- Inheritance
- Assertion
![CropperCapture[19]](http://codinginaluciddream.files.wordpress.com/2011/01/croppercapture19.jpg?w=300&h=134)
![CropperCapture[15]](http://codinginaluciddream.files.wordpress.com/2010/09/croppercapture151.jpg?w=300&h=121)
![CropperCapture[18]](http://codinginaluciddream.files.wordpress.com/2010/09/croppercapture18.jpg?w=300&h=231)

![CropperCapture[14]](http://codinginaluciddream.files.wordpress.com/2010/08/croppercapture14.jpg?w=300&h=233)
![CropperCapture[13]](http://codinginaluciddream.files.wordpress.com/2010/08/croppercapture132.jpg?w=300&h=264)