Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Derik Whittaker

Thoughts on Software Development, .Net, OOP, Design Patterns and all things cool

May 2007 - Posts

  • UI Thoughts

    I was making some changes to our app today based on some user feedback.  As I started to implement the changes I had conundrum as to what approach to take.

     

    Basically, I needed to implement changes to the UI’s behavior in certain situations based on business rules.  When needing to suppress UI actions (in terms of buttons, menu’s, etc) there are basically there are 3 options as I see it.  Enable/Disable the action, Show/Hide the action, or show/enable the action and prompt then user with a message when the attempt to perform the action.

     

    Pros and Cons (as I see it) of each method

    Enabling/Disabling

    • Pros
      • Very easy to code this
      • The user knows that functionality exits, but for some reason they cannot perform it when the button is disabled
    • Cons
      • The user knows that functionality exits, but for some reason they cannot perform it. – Unless they completely understand the business requirements they will NOT have a clue as to why the button is disabled or enabled.

     

    Showing/Hiding

    • Pros
      • Easy to code this, unless you have a complex UI
      • Removes the option from the view so the user does not attempt to perform the given action.
    • Cons
      • The visible actions list changes dynamically based on the current state. In my opinion it is never a good idea to hide actions from a user.   I would suggest that disabling would be far better then simply hiding the action.

     

     

    Prompting the user

    • Pros
      • Relatively easy to code  this
      • The user is notified that they cannot perform the selected action, and the reason should be clearly explained so they have a complete understanding
    • Cons
      • Leads the user to think the action is available until they select it.  At this point is the ONLY way they know they cannot perform this option.

     

    In my situation I went the enable/disabling of the button route.  Why you may ask?  Well because that is the pattern that the application current has.  I am would rather keep the same pattern (right or wrong) rather then implement a new one….

  • Technical Debt, How we accumulate it, and how we can reduce it

    All software projects will amass some amount of technical debt.  This is not a necessarily bad thing; it is just he cost of doing business.  As developers the only thing we can do is try to control/limit the amount of technical debt we build up.

     

    If you agree that all software projects build up some amount of technical debt then should we worry about its accumulation?  YES.  It is the type of debt that is built up and the way in which it is managed that can make the difference in a successful product.

     

    Different ways we build Technical Debt.

    • Cutting Corners
      Over the normal course of a project there are going to be times when the team or a developer will be forced to make a tough choice between doing it right, or getting done on time.  It is the classic good vs. evil (good being doing it right, evil being getting it done on time) battle in our decision making process.  The number of times we have to make these type of choices is mind blowing (my guess is that we make it so often we don’t even realize it).  However, these decision are what will mold and shape our project.  If we lean too far to the ‘Good’ side the project may slip and we will miss our deadlines.  If we lean too far to the ‘Evil’ side the project may become a maintenance nightmare and we may still miss deadlines (due to poor code maintainability/extensibility).

      When we have to cut corners, it is what we do later that will really make the difference.  If we simply mark the ‘Evil’ code with ‘TODO’s’ or throw it onto some list, hopefully we can revisit that code when we have more time to make life better

    • Lack of Cohesive Design
      Have you ever seen that car the drives down the road where the body is blue, one door is red and another door is green (not to mention the rust spots all over)?  If you don’t have a cohesive design for your project, it will end up looking like that car.  I am not saying that the design even has to be ‘good’, but a consistent cohesive design is better then no design.

      This is a form of technical debt.  Every new feature/addition to the project may become a one off.  Creating these one off’s will lead to major headaches later on as well as just poor quality. 

    • Lack of quality Business Requirements
      Most developers have learned over time how to start a new task with the minimal amount of business requirements.  We starting coding and when we hit something we don’t fully understand or know about we make assumptions (this assumes no onsite business expert). 

      When we make these assumptions they may turn out to be correct or they may not.  Even if they are correct because we don’t have a full understanding what it is we are doing we will be creating technical debt.

      In addition to this because we don’t have a complete understanding of what is needed or expected we will undoubtedly have to revisit this code later to make changes/additions.  When we do this, we may be creating technical debt because if the time is not spent to refactor/rewrite the code we may be slapping poorly thought out changes into our application.  More technical debt.

     

    Different ways we can reduce Technical Debt

    • Refactoring
      Anytime we have created any form of technical debt, whether from cutting corners, lack of cohesive design, etc, refactoring is the best way to start removing that debt.  If you can just pick one place to clean up after yourself you will be better off in the long run.

      This process may be slow and time consuming but will pay massive dividends in the future.  Oh yea, as we are refactoring, make sure we create tests for our changes if it does not already exists

    • Implementing standards/best practices
      Above I talked about if your project does not have a cohesive design you will be creating technical debt.  The best way to reduce this is to push forward with standards.  These standards may be judged as ‘poor’ by industry experts, but at least the application will be consistent.

      Start off by trying to implement either code reviews, or peer reviews.  Try to implement coding standards (don’t make the standard extremely ridge, allow developer freedom).  Most importantly try to utilize best practice design patters.

      By doing this you will start removing the technical debt you have accumulated. 

    • Reducing the degree in which we cut corners
      Try to limit the number of times you cut corners. 

      If you debating two different options and one takes 5 minutes and the other 20.  Try to lean towards the one that takes 20 minutes if it is a better solution.  However, if doing it right will take 4+ hours then maybe you have to cut the corner.  Just leave yourself some bread crumbs so you can find your way back later to refactor it.

      Plain and simple, the less ‘bad’ code you have in your project, the less technical debt you will have.

     

    Thoughts, feedback.  Agree, disagree.  Let me know

  • Some great post on the value of TDD over at Codebetter.com

    Today there are some great posts over at codebetter.com about the value of TDD.  In my opionion these are a must read for everyone.

    Great post Jean-Paul

     

  • Learning to use Mocks and the power they provide

    Up until a few months ago I had never even attempted to use mocks (NMock, RhinoMock, etc).  Every time I would read about Mocking I thought to myself, this is kinda cool, but seems to be a waste of energy.

    At the time I saw Mocks as only a way to create ‘placeholders’ for business/data classes.  I did not realize that the true power of Mocks was in the ability to isolate code that is not meant to be tested.  By doing this it allows the author to write cleaner, more reliable tests.

    Needless to say for the first few months of using mocks, I had to force myself to implement them.  Now, I choose to do them so that I can have better tests.  In fact, when I am writing new tests, the first thing I think of is, does any part of this test need to be Mocked?  Unfortunately for me, if the answer is yes, I tend to have to make changes to our application to allow for easier mocking (The initial design of the application did/does not allow for easy TDD/Mocking).

    Another thing I have learned during my journey into Mocking bliss, is how TDD and Mocking changes your mindset when designing parts of your application.  When you are dedicated to using TDD and Mocking it forces you to attack your architecture from a totally different angle.

    One of the really cool things about our profession is the ability to grow as a professional every day, if you choose to do so.  For me, learning to use Mocks is just another way I have grown into a better, more complete professional developer.


     

  • Roll Your Own vs Use Existing

    Ayende has a nice explanation on when to roll your own vs using an existing application over on his blog.

    What I like most about his post is his very simple explianation about when why he chooses to roll his own some times and use existing products at other times.

    Simply put, if the existing products are painful to use/learn it may be better to roll your own.

     

     

  • Shelf Life of a Software Application

    How long can we expect the applications we write to live on?  What types of things increase or decrease the shelf life of our applications?  Is it practical to suggest that software is only good for a certain period of time?  Or should software be able to run for ever?

     

    Most products we buy have an expected shelf life.  This is just something that most people take for granted (at least here in the US).  We know that when we buy our bright new shiny PC that it will be obsolete within 18-24 months (for power users).  We know that when we purchase appliances they will live on for 5-10 years with no issues. 

     

    So is it such a stretch to say that software has a shelf life?  If you ask most developers today, they will tell you that applications most certainly do have a shelf life.  However, ask an 'old timer' developer if their applications had a shelf life, they are like to tell you no.  In fact the shop that I currently work in still has many (way too many) AS400/RPG applications that were written 20 years ago running. 

     

    Why is it that today’s applications can have a shelf life, but yesterdays applications didn’t?  Are today’s applications more complicated?  Were the developers of yesterday better?  Short answer: Yes and No.  I would argue that today’s applications are larger in scale, which would make them more complicated to develop/maintain.  However, I would not even attempt to argue that one generation of developer was better/worse then another generation.  Today’s languages are just so different than yesterdays that it is like comparing apples to oranges.

     

    If our software has a given life expectancy what type of actions can we do to extend or shorten the life expectancy of our applications

     

    Ways to extend the life expectancy

    • Do some light weight design before you begin building the application.
      Before you begin to build your application do some upfront design.  This does not mean you have to spend months and months of time, but spend some.  Every minute you spend upfront planning will help you later on down the road.

      The upfront design will allow you to layout a solid foundation for your application.  This design could be as simple as coming up with your layers (ui, business, data) and how they are going to interact.  The could also be coming up with full blown UML models of what the application is meant to do.  To what extend you go and what you actually do is up to you, but you must do something.

    • Attempt to use as many open tools as needed to help speed up the development cycle (.Net application blocks, NHibernate, DI Containers, etc)
      Lets face it, unless your application is total revolutionary and has never been attempted before you are wasting your time not using open tools to help you solve your problem. 

      There have been many, many hours of work put into building ‘tools’ for you to use to help speed up your development process.  Use them, take advantage of them.  You will be happy you did.  Even if you have to learn to use these tools, your time learning will be much shorter then the time spend creating these from scratch

    • Take some time to weed your garden of code.
      Don’t be afraid to refactor your code (read here for ways to weed your garden).  If you don’t maintain your code over time it will become brittle and un-maintainable.  By maintaining your code base you will do 2 things.  1) You will keep the overall design/meaning of your code fresh in your head.  2) You will reduce the number of failure points by removing bad code.

    • Limit the number of corners you cut.
      Do your best to reduce the number of times you add code that is ‘smelly’ simple to meet a deadline.  We know that with every coding decision we make we have to decide between quality and speed.  Try to error more on the side of quality rather then speed.  When you do have to error on the side of speed, mark the code (with a comment, a TODO, something) so that when you have down time you can attempt to refactor the code so it is of high quality

    • Shorten the development cycles.
      If it is accepted that software has a life expectancy, then don’t waste some of that time in development.  If you can get a version of the application out to the users quickly you can effectively extend the life of the product by getting the users what they need faster.

    • Take some time to weed your garden of code
      See above J

    • Tests, tests, tests
      Have tests…… Do I need to say more?

     

    Ways to shorten the life expectancy

    • Allow the application’s design to evolve over time with little to no guidance
      Build each new feature of the application in a silo.  When a new feature/requirement is added to the application do your best to make sure that it follows the existing patterns of the application.  Even a bad pattern that is followed constantly is better then no pattern at all.

    • Don’t follow any of the above
      Do I need to say more?
    Did I miss something?  Have anything to add?
  • Coding No - No's

    Over time we all evolve as a coder, the code we write today is hopefully better then the code we wrote yesterday.  In turn, the code we write tomorrow should be better then the 'great code' we wrote today.  If this is not the case then we are not learning and evolving as professionals.

    I have put together some coding no-no's that I remember encountering over time.

    Multiple return paths in a method:
    How often have we written a method where there are mulitple logic statements that would affect the value that is returned.  When all possible have one variable that acts as the return value holder and set that value in your logic and return it at the end of your method.  I know that there are exceptions to this, but as a general rule I feel this is the best way to go.

    Good Example

    Bad Example


    Naming Confusion:
    When we declare a parameter for a method we should make sure that the parameter name is not the exact (casing, spelling, etc) same as some local instance varable.  I know the compiler will know the correct scope, but it is not fun for the developer to have to debug.

    Good Example

    Bad Example



    Finding objects based on Display Values:
    When we have a list of objects in a collection, array, etc we should always be looking for them via some sort of key.  The key value can be anything as long as it is unique.  We should never lookup values based on some string values such as a name, or display value.  This will lead to poor results as well as very poor code to maintain and extend.

    Good Example

    Bad Example



    Reuse of local variables with differnet meanings:
    When we declare a local value name it so that the intent can be clear defined, but also only used it for its intent.  Don't create a variable that is resued in the method for different intents.

    Good Example

    Bad Example

    I know there are more examples of coding No-No's these are just a few I could remember seeing in the past. 

  • Kinda like performing surgery in the dark

    Have you ever needed to make rule changes to an existing application?  I am sure you have.  Have you ever had to make these changes when you understand the change, but have pretty much no clue about the implementation of the code base you are changing?  This is kinda like performing surgery in the dark, hard to know if what you are doing is helping or hurting.

    Making changes like this can be very dangerous.  If you don’t plan this correctly you may be up a creek without a paddle.

    In my current situation I have been tasked to make some changes to an existing application where I have NO real experience in the code base, but I completely understand the changes needed.  However, the changes need to be made in 10-15 places and I no understanding of the ‘intent’ of the code I am changing.  My changes start at the data layer, go to the business layer and finally end up in the UI layer. 

    In order to minimize my risk I have devised a plan of attack which I believe will reduce my risk and set me up for the highest level of success possible.

    Steps:

    1. Create a new data access method. 
      This is needed because the signature of the data access is changing.  Doing this also allows me to change one area of the application at once.
    2. Implement the new data access method, but don’t implement the new business rules.  In my case this is possible, but may not be in all cases.
      This allows me to implement the new code without (in theory) changing the behavior of the application.
    3. Grab another member of the team who has extensive knowledge of the application and go over all points of contact for my changes.
      This allows me to have a knowledgeable sounding board for my up coming changes.
    4. Start making the changes one at a time, all the while trying to test the crap out of my changes (this project is not TDD, kinda sucks, but there are test for the data layer now)
    5. Hope, pray, wish upon a falling star that nothing I did broke things….  Guess we will find out when QA hits it L

     
    I am pretty sure that if I follow the steps above I can make the changes with very little risk.  Now the downside to this is that it will be a slow process.  But when you task a inexperienced developer (in terms of knowledge on the given project) to make changes it will always be slower.

     

     

  • Tips for writing clean code

    I came across this post about writing clean code.  Thought I would share....

    Found here


    Enjoy
     

  • Definition of 'Done'

    What is Done? 

    Done is when the software

    • has been written to address the requirements. No more, no less.
    • has a suite of tests written to exercise and validate that it meets the requirements and is technically valid.
    • source code has been reviewed by a peer, preferably peers.
    • source code meets the development teams coding standards.
    • source code has been factored into logical and easily readable sections.
    • functionality has been tested by integrating it into the system it will reside.
    • functionality has been documented and described for future developers and users.
    • has been tested and reviewed by a quality assurance expert.
    • has appropriate installation and/or configuration procedures created and documented.

     

    Can anyone think of anything else?

    (Thanks FrogsBrain for this... found this in an old email from you...)

     

  • Questions every Candidate should ask a potential new employer

    Over the years I have conducted my fair share of interviews with potential new employees for the different companies I have worked for.  In fact my company is currently looking for a few good developers now.  What has always confused me is the lack of questions asked by the potential candidate.  Sure they ask the standard stuff like vacation, benefits (pay, 401k, insurance), work/life balance, company history.  However, most fail to even mention anything about the team, the environment or the companies philosophy towards software development.  If you ask me, knowing how the team is structured/ran is more important in some respects then ‘standard questions’.

     

    I put together a quick list of questions I would expect a top flight developer to ask, please feel free to add your own.  NOTE: These are not in any particular order

     

    1. Explain the company’s development process at a high level.
    2. How are releases scheduled/planned, do you utilize iterations
    3. Do you have dedicated environments (development, qa, stage, production)
    4. Do you follow any formal methodology (agile (what flavor), waterfall, etc)
    5. What is the company’s philosophy on team member involvement in the SDLC process
    6. Do you have a continuous build environment setup
    7. Do you follow some form of TDD
    8. How do you track/follow bugs/issues
    9. Do you perform code reviews
    10. What type of development tools do you have
    11. What type of hardware for the developers to you have
    12. Is QA involved from the onset of development
    13. Do you have a knowledge center for the team such as a team portal, wiki, etc
    14. Do you have up to date specs on the application
    15. What form of stake holder involvement is there in the development cycle
    16. Do you have documented coding standards, are they followed

     

    What did I miss?

     

  • Cyclomatic Complexity Measurements: Simple code == Better application

    We all know that simpler is better when it comes to software development.  Any time there is code that is overly complex it makes it hard to test/debug and it is much harder to interpret in the future when changes/enhancements need to be made.  There are a few different ways that developers can attempt to keep their code simple.  We can use techniques such as Functional Decomposition, we can conduct code reviews, TDD, adopt pair programming, etc.

    There is another way we can attempt to keep our code simple.  We can measure our code based on the Cyclomatic Complexity measurement.  This is a software metric that attempts to measure the ‘pathways’ through a method/module (read the wiki for a better definition).  [Google Search on Cyclomatic Complexity]

    One way to measure the Cyclomatic Complexity of your application is to use a existing tool.  I have chosen to use a plugin for Reflector by Lutz Roeder.

    After you have downloaded/installed the plug-in, fire up Relector (this assumes prior knowledge of how to use Reflector) and load the assembly you wish to view.

    In order to run the code metrics you need to select the assembly from the tree view in Reflector then go to Tools -> Code Metrics.  This will open up a new panel with the different possible assemblies to run the metrics against.  Check the one you want and click the refresh icon in the tool bar.  This will run analysis for your assembly.  When this is done, it will give a listing of the results for each class.  If you wish to view the results on a per method level, simply change drop down to ‘Method Metrics’ to refresh the list for methods.  You will now be able to sort the results any way you want.  I like to sort by the CyclomaticComplexity rating.

    If you see methods with a rating of 10 or higher you may want to spend a few minutes to see if there is any way to improve this logic.  The goal would be to have no methods with a complexity of 50 or higher, while having most of your methods have a complexity of 20 or less.

    Complexity Threshold Values
    1 - 10: Simple Program, without much risk

    11-20: More complex program, moderate risk
    21-50: Complex program, high risk
    > 50: Untestable program, very high risk


    I like to spend a few minutes here and there to run this on my applications in order to get a view of what is going on.  Learning to use this tool effectively will make your code base simpler, and your application better.  Both of these are keys to success in the software world.

    Enjoy…

  • What's wrong with this block of code??? Buellerrrrr, Buellerrrrr

    All, just came across some 'interesting' code today.  Can anyone point out what is wrong with this?


    public bool SomeMethodNameHere( bool someParamNameHere )
    {
        if ( this == null )
        {
            return true;
        }
            else
        {
              ....
        }
    }



            
     

  • Object Construction – Constructing for Success

    I have finally come to the conclusion that no object should be allowed to be constructed in any way that will allow for the object to be setup in an invalid state. 

    Way too often I see an object that uses the empty constructor which then requires the user to ‘guess’ which properties are needed to setup the object correctly.  This in my opinion just leads to poor code and really hard to find bugs.  I would suggest that if an object needs certain values to be considered ‘valid’ then these values need to be provided during construction.

    Imagine if you will you have an object; let’s call it the ‘Manager Object’.  In order for this object to be valid you need to provide it with the ‘ID’, ‘Name’ and ‘Authority Level’.  If you have an empty constructor, the users of the object must KNOW those values are needed.  If they don’t provide them very odd/subtle bugs may appear.

    Now if your object’s constructor (or builder, factory, what ever) required those values at construction time no one would be able to build the object in an invalid state.  You could even go as far as asserting the values passed in to make sure they are within valid ranges.

    By requiring your objects to be constructed in valid state at all times you will have more confidence in your app as well as a cleaner code base.  Oh, and by the way, the I would also suggest that the properties are read-only UNLESS EXPLICITLY needed for setting, this will also enforce a more stable object.

    Finally, I know this seems way too obvious to many as simply best practice.  However just because it is obvious does not mean it is followed...... :(

     

  • VS 2005 Annoyance -- "Not enough storage is available to complete this operation"

    Has anyone else seen this message when trying to compile a solution?  My dev box has 2 gigs of memory with about 1 gig free when i get this.  I get this about once or twice a week.

    The only way to get around this is to restart the IDE, kinda annoying....

    Has anyone else seen this?
More Posts Next page »

Our Sponsors

Proudly Partnered With


This Blog

Syndication

News