Showing posts with label style. Show all posts
Showing posts with label style. Show all posts

Monday, October 5, 2009

Reasons to NOT put version history in the comments

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/reasons_to_not_put_version_history_in_the_comments.htm]

Some coding standards ask that developers add revision history to the top of the method. Not just the normal "Summary" and "Parameter" tags that can be used to automatically create documentation, but rather a full blown revision log with developer name, date, and comment. This was bigger in the 80's and 90's, when source control and refactoring weren't as common. However, in these days, putting revision history in your comments has some really big problems:
  • Extra effort - It requires extra effort from developers, and usually the tedious kind of effort. It requires manual developer discipline, so architects don't have a good way to enforce this.
  • Bad for refactoring - It discourages refactoring of methods. Say you split a method in two - how do you split up the commented version history?
  • Source control already provides this - It doesn't tell you anything that source control history won't already give you. But even worse, it could be misleading - source control is the true authority, a developer could accidentally type (or forget) the wrong comments. Also, by documenting at the top of the method, it is hard to indicate what changed in the middle (whereas source control diff would instantly tell you).

Perhaps for SQL, I can see the benefit, so that when the DBA runs sp_helptext on a stored proc, they get a quick history (and databases aren't usually refactored like C# code). However, for middle tier code, putting revision history in comments seems like an unwise use of time.

LINK: Comments as version control
 

Monday, November 10, 2008

More Xml Design Patterns

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/more_xml_design_patterns.htm]

 

Last month I mentioned some tips for structuring xml, which could be seen as the start of primitive Xml Design Patterns. Here are three more ideas.

 

Strongly-typed nodes

 

Say you have a node, which can have several different groups of attributes. For example, you're making a test automation DSL, and you need to assert that various conditions are met. You may have a basic assert, a correct-page assert, and a text-search assert:

The schema for this becomes messy - you'll have one node (Assert) with all possible attributes. Your interpreter will need to infer which action to take based on the current attributes. Validating the xml file also becomes error-prone. It's doable, but messy. Compare that to this:

.Page pageName="myPage.aspx" />

.Text textToFind="EmpId123" isRegex="false" isCaseSensitive="false" />

This approach has essentially three nodes: Assert, Assert.Page, and Assert.Text. This effectively gives you "strongly-typed nodes". Your interpreter instantly knows which type of node, and therefore what action it expects and how to validate its attributes. Your schema becomes simpler because each node type has only the relevant attributes. This isn't always the best approach, but it can be a good one in certain cases.

 

 

Serializing complex objects to attribute strings

 

You can serialize almost any object to Xml, but the question is what is the best way to do it? For example, you could serialize an array as a bunch of nodes:

   

        12

        35.5

        40

        9

   

However, this is somewhat bloated. A more concise way is to serialize it to a string, and then store the results in an attribute:

You could serialize an array as a CSV list: "1,2,3".

You could serialize a name-value pair: "name1=value1;name2=value2" (this is what MSBuild does)

You could even have a mini DSL, like the Silverlight path expressions: "M 10,100 C 10,300 300,-200 300,100".

 

The main thing this approach requires is an easy way to serialize and deserialize the object to a string. If you've got that, then this technique becomes very reasonable.

 

 

Abstract complex objects to inner content

 

Silverlight uses Xaml markup to describe the UI. Xaml allows a lot of style markup.

 

You can create a simple ellipse, shading the entire thing a solid blue.

Fill="Blue" />

However, you can also give it a more advanced two-color gradient shade by abstracting the "Fill" markup to the inner nodes of the ellipse. Specifying a single attribute is great when you can serialize all the necessary info to a single string, else you can leverage the more-powerful inner xml nodes (per a Jesse Liberty tutorial).


   
     
        
        
     

  

This allows the best of both worlds - the single-line common case, and the more advanced case.

Thursday, October 9, 2008

Xml Design Patterns

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/xml_design_patterns.htm]

Xml is the defacto way to store data in files - whether it's build instructions as an MSBuild script, a Domain Specific Language based on code-generating from an xml filea config file, or something else.

 

So, your xml files are storing lots of mission-critical information. They're getting huge, being modified by tons of developers, and getting hard to maintain. It's time to refactor them. Here are several ideas to refactor your xml files (much of this is demonstrated in MSBuild):

  • Create a variables section. For example, MSBuild has a  section, where each inner node can define a new variable. You can then reference those variables elsewhere throughout your script like so: $(myVar).

  • Allow importing of files. Often you'll want to either split a big file into smaller ones, or reuse a single file many times (for example, put all your global variables into a separate file, and then re-import it everywhere).

  • Related to this, allow chunks of xml to be automatically included in other chunks with some sort of "include" syntax. In other words, ensure that the xml file itself is refactored. MSBuild allows you to call other targets with a task. Or, say you have a test script that's generated from xml, and every test needs to repeat your "login routine". Define the login routine in one xml snippet, and allow it to be re-included in all the other snippets.

  • Have the xml structured to automatically determine relationships. For example, if you have a parent-child relationship of data (here is the menu, here are all the pages accessible from that one menu), then consider using Xml's natural hierarchy (a

    node with a bunch of child nodes). You could also use the natural order of the xml nodes to determine the natural sequence that the data appears (like the order of the pages).

  • Provide some way of an extension method or hook. In MSBuild, you can define your own custom tasks and dynamically load them.

  • Create special syntax for domain-specific concepts. For example, the MassDataHandler takes xml snippets, and converts them to SQL insert statements to assist with database unit testing. A common problem for inserting SQL statements is handling the identity columns. In this case, if you prefix the value with an '@', the MassDataHandler automatically knows to go lookup its identity value.

  • Create templates for default values, which other xml nodes can override. For example, the MassDataHandler allows you to run SQL inserts, one xml node per database row. But say five rows all have the same values for something (like they're all children of the same parent), then it provides the ability to have a "default row" which defines the default values. Other xml nodes can then override these default values.

I guess you could say there are design patterns for good xml. As Xml becomes more and more prevalent, I expect that "Xml Design Patterns" to become more prevalent too.

Monday, September 29, 2008

Death by a thousand cuts

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/death_by_a_thousand_cuts.htm]

A single paper cut won't kill you, but a thousand of them probably will. That's what people mean by "death by a thousand cuts". This is how many software projects die - it's usually a hundred little things that pile up, and whose combined pain becomes unbearable. It's the runaway bug list, the brittle test script that gets abandoned because it's too hard to maintain, the endless tedious validation on a details page, the component with the fuzzy interface, the buggy deployment, all the little features that just don't work right, etc...

 

This is why continuous integration, unit tests, automation, proactive team communication, code generation, good architecture, etc... are so important. These are the techniques and tools to prevent all those little cuts. I think that many of the current hot methodologies and tools are designed to add value not by doing the impossible, but by making the routine common tasks "just work", so that they no longer cause developers pain or stress.

 

Sure, you can write a single list-detail page, any developer can "get it done". But what about writing 100 of them, and then continually changing them with client demands, and doing it in half the scheduled time? Sure, you can technically write a web real-time strategy game in JavaScript, but it's infinitely easier to write it with Silverlight. Sure, you can manually regression test the entire app, but it's so much quicker to have sufficient unit tests to first check all the error-prone backend logic.

 

The whole argument shifts from "is it possible" to "is it practical?" Then, hopefully your project won't suffer death from a thousand cuts.

Tuesday, July 1, 2008

Why you shouldn't just wrap simple code in a try-catch

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/why_you_shouldnt_just_wrap_simple_code_in_a_trycatch.htm]

Structured programming languages, like C#, provide a try-catch ability to wrap an entire block of code, and catch if anything goes wrong. This can massively simplify error checking, especially when calling external components. However, like any good thing, it can also be abused. During interviews, or rushing out code, many developers resort to using try-catch as a quick way of doing error checking, but there's a catch (excuse the pun). For example, consider this trivial method to sum up an array of integers:

 

    public static int GetSum(int[] aInt)
    {
      int intSum = 0;
      foreach (int i in aInt)
      {
          intSum += i;
      }
      return intSum;
    }

 

You can crash this code, such as by passing in null for the int array.  To blindly wrap a simple method with try catch, just to catch normal logic errors like null variables or indexOutOfRange, has problems.

  • For performance, Try-catch is enormously expensive compared to an if-then check. It could be hundreds of times slower. So it's bad design to use a try-catch for something trivial when an in-then will do just file, like checking if a variable is null.

  • What will you do in the catch statement? Some devs may say "I'll log my exception info here" - but what info is that... that the developer didn't bother to do basic error checking?

  • It makes the usability worse. Perhaps instead of re-throwing an exception, or logging and going to the global error page, the method could have used an if-then to return a sentinel value instead. For example, perhaps a string manipulation method could just return the original value (or null) if the input parameters were invalid.

  • It loses context. Say your code catches a null exception - that thrown exception doesn't tell you what variable was null. You've lost context and information with which to fix the code. Using an in-then would have given you full access to all the local variables and their context.

  • It makes all exceptions equal - a null or indexOutOfRange exception (things that are easy to catch with if-thens) are put on the same level as a critical outOfMemory error - i.e. both trigger the catch block. This in turn can distract the maintenance team, who gets swamped with tons of exceptions, most of them preventable.

  • Perhaps worst of all, it implies that the developer isn't thinking about how their method can fail. Rather than understanding the code and what it does, they just wrap it all in a try-catch, and move on. This means they could have not coded for valid use cases.

Try-catch has obvious benefits, but it has limitations and consequences too. There are times when it's much more beneficial to explicitly catch the error conditions with an if-then instead.

Wednesday, May 14, 2008

Beyond functionality for enterprise apps

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/beyond_functionality_for_enterprise_apps.htm]

Many developers are so pressured by demanding schedules that their goal is just to "get the job done", by which they mean "it functionally works." While this is a great first step, professional programming requires more, such as:

  • Maintainability

  • Performance

  • Scalability

  • Security

  • Testability

As you go from a hobbyist toy to an enterprise app, these criteria become self-evident. They're buzzwords that everyone has heard, but surprisingly few seem to put into practice. Interesting questions to ask yourself (or someone you need to interview):

  • Maintainability - Have you ever had to write code that will be maintained by other people? How did you code differently to make it more maintainable?

  • Performance - Have you ever had to write code that was performance critical? How did you ensure that that code was fast enough?

  • Scalability - Have you even had to write code that was used by more than 1 million users? What might you do differently to ensure the code handled that?

  • Security - Have you ever had to write code that protected secure data and you knew someone would try hacking it? How did you make it secure?

  • Testability - How would you ensure that your code could be tested?

Of course some of these, like performance tuning, may take more time. But that goes with the territory of large-scale apps.

 

In general, I come across two kinds of programmers - those that just worry about functionally "getting it done", and those that look beyond functionality. It seems the first group digresses into boring copy and paste work, whereas the second is constantly on an adventure doing new, fun things. The beauty is that there's nothing that stops someone from jumping into the second group. You can read about all the techniques online, use open-source tools, and often it's even faster. For example, anyone could use NUnit, or MSTest to write unit tests to help their testing, or read about Refactoring or design patterns for more maintainable code.

Tuesday, May 13, 2008

"I know the concepts, but not the syntax"

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/i_know_the_concepts_but_not_the_syntax.htm]

I hear it a lot from developers - "I know the concepts, but just not the syntax." The thinking seems to be:

  1. There's too much out there and I can't know it all

  2. The concepts are what really matter

  3. The syntax is just trivial stuff that I can look up.

Therefore, the idea is that the developer knows the important stuff (concepts), and shouldn't be blamed for not knowing the unimportant stuff (syntax). Fair enough as long as you know enough syntax to get the job done. However, more often than not, I see developers who continually shrink the first category and enlarge the second. For example, I've seen developers refer to standard concepts for which they're heard the buzzword but don't understand (OOP, exception handling, n-tier architecture, client-server models, design patterns, etc..) as "syntax". Some people think this is a smart way to avoid saying "I don't know." The problem is that these things are not syntax - syntax is language specific details for a single implementation. For example, various languages can each have their own syntax to create comments. The concept is "creating a comment in code", the syntax is what you actually type to do it (such as // or /* ... */ in C#).

 

A general rule is that concepts transcend any one language. For example, C++, Java, and C# all use OOP, so questions like "What is an abstract class" or "What is polymorphism" are conceptual questions - they have nothing to do with syntax. Likewise, all these xml config files (like the ASP.Net web.config, or even MSBuild) have little to do with syntax - the whole point of making them in xml is to bypass any syntax problems. Rather, they're about "do you understand the problem space?" If you know the concepts to tune a web application, ASP.Net's web.config suddenly makes a lot more sense.

 

I realize at the end of the day, implementation requires us to know the syntax. In fact, many developers can copy and paste chunks of code without even knowing that conceptually is going on. To such a developer, everything is effectively syntax. However, there's always the benefit of being able to step back and differentiate between the two.

Monday, February 11, 2008

Slow and controlled over fast and uncontrolled.

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/slow_and_controlled_over_fast_and_uncontrolled.htm]

In my personal experience, I notice that most developers would rather user a technique that takes longer (but for which they have complete control over), then a faster techniques (for which they can't really control). They want a slow and controlled shot over a faster, but random, one. For example, they'd rather use

  • A cumbersome open-source project (which lets them step through and modify all the code), than a powerful framework that they cannot modify.

  • An older technology that they've mastered, than a new one that "sounds" promising.

  • Their own code (that they know inside out), than someone else's, or a third-party, that's obscure.

To some degree, this makes sense. Who cares if a technology or component is powerful if you cannot harness that power? The problem is if you cannot control the code, it becomes not just useless, but rather dangerous. The un-intended consequences will kill your schedule. However, good developers need to constantly learn, and tame those powerful, yet still-wild, technologies. For example, a developer may be afraid of regular expressions, and comfortable writing tons of string-parsing code, but ultimately they need to learn regular expressions.

Tuesday, January 22, 2008

Purist vs. Pragmatist

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/purist_vs_pragmatist.htm]

I've seen a lot of different developer personalities over the years. Two main groups, who always seem at odds with each other, are the "purists" and the "pragmatists".

 

Here's a brain-dump based on my personal experience:

  • The purist wants to do pure, perfect coding, and never get their hands dirty with un-pure code.

  • The pragmatist wants to get the product shipped and make the client happy, but may take hacks and shortcuts to do so.

I see pros & cons to each approach.

 

 ProCon
PuristPRO: Always trying to do it right, wants to avoid hacks that would be costly later on.

PERCEPTION: Seen as visionary leaders whose best-practice principles set the entire project on the right path, and spares the team from endless hours of hacks.

EXAMPLE: "This is a 3 month project, we're going to take the first week and set up a build server with proper continuous integration".

FAVORITE SAYINGS:

  • "We got to do this right"
  • "These are the best-practices"
  • "Look at the rate-of-return"

 

CON: It is easy to be a purist on paper, or with the easy problems, but the mess of the real world (deadlines, client changes, complex technology, personality differences) means that we often need to make compromises that aren't always perfect.

PERCEPTION: Seen as ivory-tower elitists who never actually get the job done because they keep waiting for the perfect component in an un-perfect word. A purist is more talk than action, and because it's easy to talk, purists are always asking for the impossible. If a purist actually had to do it themselves, they'd act like pragmatists.

EXAMPLE: "That fileCopy utility (used only for internal development) isn't good enough because it may not handle the new encoding standards in three years, you need to re-write it from scratch."

FAVORITE SAYINGS:

PragmatistPRO: Focuses on getting the job done so that the company stays in business.

PERCEPTION: Seen as the "real workers" in the trenches who get the job done.

EXAMPLE: "It'd be nice to have a script that automatically deploys the entire product, but there are some third-party manual GUI configuration steps that we just cannot automate yet"

FAVORITE SAYINGS:

  • "Talk is cheap"
  • "It's easier to describe than implement"
  • "Show me a proto-type"
  • "How will you find schedule time for that"
CON: The pragmatist may get so caught up in "just getting it done", that they always take the immediate solution, which is usually not the best long-term solution.

PERCEPTION: Seen as desperate hackers who get the current product out only by writing mountains of bad code, for which the purists later spend 10 times the effort to fix.

EXAMPLE: "This component is due next week, I'll just copy this code to ten different places because I don't have time to refactor it."

FAVORITE SAYINGS: (bad if used as a justification to commit some hack)

  • "We got to get it done"
  • "We don't have time".

 

You could simplify this as the purist is obsessed with the cause (we'll do it right, no matter how long it takes), the pragmatist is obsessed with the effect (we'll ship a product, even if we need to cut corners).

 

Of course, I think the ideal approach is a balance. The very good book, The Pragmatic Programmers, shows many such balanced-techniques. Sometimes, you'll be forced into a hack - but there are still good ways to handle that. It also helps having a team with a range of these personalities so that people can hold each other accountable and bring out the best in one another.

Thursday, December 13, 2007

Architecture: Keeping it non-exponential

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/architecture_keeping_it_nonexponential.htm]

Systems have a tendency to get more disordered. Architecturally, it's easy to always take shortcuts such that your application code becomes one big mess of tightly coupled objects and duplicated code. It starts innocent enough -you have only a few initial components, and each one has a dependency on the others. So that's still only a few dependencies.

But then, a few emergencies later (and what isn't an emergency?), your code has ballooned, and the dependencies have exponentially exploded into a mess. The project has accrued so much technical debt that the schedule is hopeless, and it's no longer fun. Every object is intertwined with every other object:

A much more sustainable model is to demand cleaner code at each step of the way, and end up with something maintainable, which the number of dependencies increases linearly with the number of new components. This lets you add, remove, and modify the code much more easily:

I see this as one of the basic issues of architecture: keeping the ever-growing code base in a maintainable state. In application development, this often boils down to conscious decisions where everyone "knows" the right way, but instead write sloppy code for ("we don't have time", "we'll fix it later", "this one won't hurt", "it works", "the maintenance team will fix it", etc...). Often, it seems like the team just needs a strong and credible voice to encourage everyone to do the right thing. Especially for long-term, enterprise projects, this seems like the optimal way to go. It sure beats having 12 months of garbled code.

Sunday, December 2, 2007

10 Rules that Age of Empires Teaches about Development

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/10_rules_that_age_of_empires_teaches_about_development.htm]

I think that Age of Empires II (AoE) is arguably the best computer game of all time. A close second would be Civilization IV. I'm not much of a computer game player, so the best way for me to justify playing a game is that it's somehow educational. Smile Here are 10 rules, that Age of Empires clearly demonstrates, which also apply to software engineering:

  1. You need to invest in research: This means the occasional big investment, as well as many frequent upgrades as resources allow.  If you neglect your research, it won't matter if you have a hundred units - they'll all be obsolete and practically useless. It may even backfire because you'll still have to maintain them (via population limits or distracting your "medics" to get healed), which will prevent you from focusing on the new, important units that can actually win the game.

  2. You need the right tools: Don't even try taking down a castle with just stone-age sling shots. Often you need a combination of complementary units - i.e. you need to coordinate siege, cavalry, medics, etc... Likewise, software engineering needs the right tools - good luck with team development if you don't at least have a good source control system and a build server.

  3. Strike a problem while it's still small: Like in real life, problems grow in AoE. An enemy team gets bigger and stronger, resources dwindle, or the clock runs outs. This is why a common strategy is to rush your opponents while they're still small. (You may also be small at the moment, but you're still big enough to beat them now). In development, problems grow too - bad code propagates. Knock it out early before it comes back to bite you.

  4. Protect your home base: Don't rush out on some adventure and leave you home base defenseless. Likewise, in development, your core application is your home base, and it should be protected by a suite of automated unit tests. So if you get distracted with some other "adventure", at least your code still has some defense against bad additions that would break it.

  5. Not all units are equal: Although a foot-solder and a horse-archer are each just a single unit, one horse-archer could beat ten foot-solders. Furthermore, the horse-archer, who can shoot at range (like across a river), could accomplish things that a million foot-soldiers could never do. Likewise, in development, there are real "stars" - a star dev will produce not just more than 10x an average dev, they'll create things that an average dev won't even comprehend. Granted, sometimes a company's technical needs are simple enough that they don't need stars, but it's good to at least be aware of the discrepancy.

  6. Your plan can be limited by mental energy: You may have 50 units, but it doesn't matter if it's impossible to manage them. AoE is an arcade game, and you may make dumb decisions simply because there wasn't enough time to think out the perfect solution. I personally prefer a handful of powerful units that are easy to manage, as opposed to an army of weak units that just get plucked off because they're too hard to coordinate. Same applies to software engineering, but even more so. Most of what you do is limited by mental energy (code being hard to maintain, a purist algorithm taking too much thinking to figure out, etc...). Mental energy is as real a resource as gold.

  7. Don't rely on cheat codes: AoE has cheat codes. However,  don't depend on them because they could be disabled or make you miss the bigger picture. In software engineering, the equivalent is to use hacks - bad code that solves the immediate problem now, only to break tens times as much later.

  8. Expect the unexpected. In AoE, there are other teams actively working against you. The enemy may not attack your straight on (where all your defenses are), but may instead be creative and attack from the side, or ambush behind, or siege you, or something else. Likewise, in software engineering, there are constant business changes, miscommunications, developer bugs, new technologies, all causing unexpected things to happen.

  9. Recognize the common patterns and solutions: AoE has perhaps hundreds of units. With many different civs (each with their own unique unit), it's a lot to have a special plan for every single unit that you may encounter.  However, there are comparatively only a few categories for them - like infantry, ranged, cavalry, siege, naval units, etc... By looking at the common patterns (ranged units usually beat infantry, cavalry usually beats siege), you can abstract out the details and make a flexible plan. Same thing in software engineering - there are common design patterns and ways to abstract out complexity via domain-specific-languages. Be prepared to look at the high-level abstract issues, then drill down into the details.

  10. It should be fun: AoE is a good, old-fashioned-fun kind of computer game. It has huge replay value. Likewise, development should be fun, especially if you have the right process and schedule in place.
     

Wednesday, October 3, 2007

Five hours for one line of code

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/five_hours_for_one_line_of_code.htm]

The other day I spent five hours to write a single line of code. This has happened before, and it always makes me think "why?" To the non-developer it could sound crazy, I've heard many say things like: "it was just one line; you should be writing 100 line of code per hour to justify our budget."

 

The issues involved are:

  1. The developer is working on a legacy sub-system that they had never seen before (perhaps the original creators are no longer available, and you need to dig through their work)

  2. That sub-system is written in a different language

  3. The sub-system itself was complicated

  4. The line to be added was an undocumented feature

  5. It took very long to test each change

  6. This was a mission-critical feature, so it needed to work perfectly

You add those all together, and it's easy to see it the other way - "Wow, I'm glad we got that handled in only half a day".

 

Also, this is a rare case. A developer can write many lines of new code per day.

 

I think it touches on a bigger issue - just because the end result is simple doesn't mean that finding that result is simple too. For example, the total population for the US at a given moment is a specific number (somewhere around 300 million, off the top of my head). However, to find that exact number requires a huge bureaucracy and coordination among many civil organizations (like hospitals and immigration offices).

 

It something that any developer could come across, and should therefore be prepared to explain to their managers if needed.

 

Wednesday, August 15, 2007

The Developer's version of Maslow's hierarchy of needs

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/the_developers_version_of_maslows_hierarchy_of_needs.htm]

We all know that there's a list of buzzwords that every app should have - it should be secure, fast, maintainable, functional, and reasonable to build. However, not everything is equal - just like there's Maslow's hierarchy of human needs, there's also a developer's hierarchy of needs. This is how I'd currently rank needs for the an enterprise app:

  1. Functionality - Ignoring security, performance, and anything else, the bottom line that every dev wants to show their client is that the app functions correctly. It the app doesn't even save results or calculate correctly, nothing else matters because no-one will pay for it.

  2. Security - This is really an extension of functionality. An unsecured app can be worse than no app at all.

  3. Build-ability: Can it be built? - I think that functionality trumps build-ability because developers will often learn new languages in order to meet the functional requirements (i.e. a dev learns html in order to functionally create a web app). We'd all love bells and whistles, but if a developer can't build it, it doesn't matter. This is why I'd rank the ability to implement above performance. For example, most developer choose C# over Assembly Language because it's more feasible to program in C#, even though Assembly is obviously faster.

  4. Maintainability - every app must be maintained. If the maintenance is impossible, it will drag everything else down with it.

  5. Performance - Performance is great, but only after all these other needs are met. Who cares how fast it is if the app doesn't do what you want, will likely get hacked, or just is too costly to build and maintain?

  6. Bells & Whistles - Every dev wants to sneak in some awe-inspiring bells and whistles, but as far as business goes, that's last on the list. This is why many development shops lag behind the latest technology, because they view the fancy features it provides as still unnecessary luxuries. For example, an app may not yet have fancy AJAX controls or a flashy GUI because they haven't gotten the more important needs met first. If a team has the first 5 needs met, then they'll be in a much better position to explore the "cool" tricks of the latest technology


Living in Chicago and interested in working for a great company? Check out the careers at Paylocity.

Tuesday, August 14, 2007

How easy maintenance will improve performance

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/how_easy_maintenance_will_improve_performance.htm]

We all want our software apps to perform fast, however sometimes we get so obsessed with immediate performance that we neglect the big picture and actually code in a way that degrades performance in the long run. The problem is that optimizing code for performance usually (1) takes more development resources, and (2) makes that code harder to maintain. About the second point - there is often a tradeoff between performance and maintenance: generalized code is easy to maintain, but because it handles all general cases, it is not optimized for speed. For example, it wastes extra resources on tasks that may not be needed for the current case, but are still included so that the code handles the general case.

 

So, the trap becomes a developer may spend all their resources upfront trying to optimize a specific component. However, if that component isn't truly performance-critical, then they've: (1) spent their resources on a non-critical item such that they have less resources for the really critical ones, and (2) created a maintenance issue that will continually drain their resources away from the components where a little amount of effort could really optimize it.

 

What this means is that, in the long-haul, writing maintainable code (which may be slightly slower) will actually yield overall performance gain because you'll continually have move resources to address the real performance problems. Functionality trumps performance - if your code functionally doesn't work, you won't care about performance. So if you're continually being distracted to go and fix bugs in old code because it isn't maintainable, you'll likely shift your mindset from "make this work fast" to "just get it to functionally pass". Of course the trap is that a developer starts out with good intentions - "I was just trying to optimize this code".

 

The optimal approach is to strike a balance between maintainability and performance. Some practical tips:

  • Not all code is equal - obviously code that is frequently called needs much more attention that code that is rarely called.

  • Check where your bottlenecks are. For example, if your database is ground to a halt, and your web servers are relatively free (keep in mind that web servers scale much more easily than database servers), killing yourself to optimize a simple codeBehind page may steal mental resources from optimizing the real issue - a database. Likewise, don't waste time trying to compress all your JavaScript, just to save 5 k of download, if that JavaScript now becomes impossible to debug or maintain.

  • Know what the standard is - Everyone knows that the app should be "fast", but how fast is fast enough? Clichés like "as fast as possible" are what get you into the downward spiral because they encourage you to squander resources on less-important tasks. If you know that given X users, a page should take Y seconds to load, then you can make rational decisions on how to spend your development time wisely.


Living in Chicago and interested in working for a great company? Check out the careers at Paylocity.

Wednesday, August 8, 2007

Coding can be like running a marathon

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/coding_can_be_like_running_a_marathon.htm]

Coding can be like running a marathon - you're in it for the long haul. If you "sprint" upfront (hacks, skipping process, un-maintainable code, one-off copies) just to get it done, you start off ahead. But as you need to make maintenance and architecture changes further down the road, all those hacks have caught up with you and the code has become too hard to change. Each new feature becomes like a runner dragging them self to go one more mile. Both marathoners and software applications need to be prepared to run for a long time.

 


Living in Chicago and interested in working for a great company? Check out the careers at Paylocity.

Wednesday, July 25, 2007

How normal life experience helps you better understand software

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/how_normal_life_experience_helps_you_better_understand_softw.htm]

There are some things in software engineering that are hard to explain, or hard to convince others to do. One benefit of normal life experience, i.e. things besides programming, is that they can sometimes more effectively explain those difficult concepts by emphasizing them in a different context.

Most excuses for bad code come from "I don't have time to do it properly", or "It's just throw-away code for my own personal use, it will never be used in production." Yeah right. There are so many developer bad practices with analogies to normal-day life activities that show how silly these excuses are.

For example, here's a partial list

  • Bad Labeling - Many developers give their variables and methods useless names, such as "x1" or "DoEverything()". But we label things in normal life, like our luggage that we check in at the airport, or boxes when moving houses. Imagine how silly (and time-consuming) it would be to refuse to label your luggage because "you don't have time - I'll just look for the black suitcase".
  • Packaging and a clean contract - lots of code has messy contracts - it's not clear how to call the code, or where the code's responsibility ends and the consumer's begins. Apply this to moving houses - the contract is clear - you put things in designated moving boxes (packing them within those boxes however you see fit), and the movers haul them to the new location. Imagine the mess if you "didn't have time" to pack the boxes. Some movers will still do it for you, but it will cost a lot more.
  • Kicking off  a process - a lot of developers program only in series. But in real life we often kick something off while we go do another thing - for example with chores like starting the dishwasher, letting things dry or melt, or letting plants grow. Once you kick these things off, they're easy to maintain. But if you wait until one such task is finished before starting the next, you'll never get all the chores done.
  • The cost of failure - in most engineering practices, failure can be devastating. If your car breaks down on the highway, it's bad. In civil engineering, a failure in a bridge or building could cause the entire structure to collapse and cost lives and tens of millions of dollars. In software engineering, a lot of developers don't really account for potential failure (error checking code, security flaws, bad logic, etc...). Software has errors for several reasons, including that software engineering is still relatively new and people are still amazed that software actually works, management doesn't want to pay to ensure that program works, or because it's just hard making something be solid. Either way, in software engineering it can be easy to ignore the cost of failure, but this can be much clearer in other fields.
  • The need for peer review - In most daily activities you'd ask for help if something is complicated, whether it's asking for directions while driving, or how to fix an appliance in your house. However, it still amazes me that many management teams develop incredibly complex applications, but don't want to "waste" time reviewing that error-prone work. It's almost as if some teams spend more time reviewing how to fix their $50 toaster than how to check their $500,000 software application.

Experience in software engineering is great, but there are some concepts that are just really easy for some people to understand outside of a software-engineering context. Once understood, they can then re-apply to their engineering discipline.


Living in Chicago and interested in working for a great company? Check out the careers at Paylocity.

Monday, March 12, 2007

Why the "not-built-here" mentality

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/why_the_notbuilthere_mentality.htm]

A lot of developers have the "not-built-here" mentality - i.e. they only want to use code that they (or their department) built themselves. Here's a brainstorm of some ideas why:
  • Concern that external component won't actually work or fit their needs
  • Too difficult to customize
  • No fun to just plug in someone else's component - devs want to build it themselves
  • External components often have license fees (turns off managers and business sponsors)
  • Too many unintended side affects (i.e. an AJAX web control that can't handle being on a page with a postback)
  • Developers think that they can do it better than the external component
  • Fear that product won't be maintained (perhaps from a bad customer service experience)

Of course the benefit of using a third party control (especially an open-source one) is that it can save you a ton of time, potentially give you things that you could never build yourself, and provides you something far more standardized.

Monday, February 26, 2007

Good book: The Pragmatic Programmers

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/good_book_the_pragmatic_programmers.htm]

I recently finished a good book, The Pragmatic Programmer, by Andrew Hunt and David Thomas. (I had read their Unit Testing book a while back).

What I liked to much about it was that:

  • It really was practical
  • Andy and Dave are good writers, with a down-to-earth style
  • It transcended the current technology (much like Code Complete)
  • It addressed a huge range of topics, from automation to testing to team culture. Software engineering isn't just about a lone-wolf developer typing the write code. Rather, it requires a huge breadth of skills and process.
  • It boiled things down to specific tips.
  • It pretty much takes a bunch of lessons that I learned the hard way and presents them.
  • It's short - maybe 250 pages (not including appendix, references, etc...)

I wish I had read this five years ago.

Monday, January 22, 2007

What would it take to be twice as productive?

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/what_would_it_take_to_be_twice_as_productive.htm]

Often you can improve the future by learning from the past. Given that we always want to be able to develop faster (given the same level of quality, energy, etc...), it merits reflecting on the question: What would it take to be twice as productive?

Here are some general ideas I was thinking about:

  • Better tools (like a CodeGenerator or Resharper)
  • Better hardware - a fast machine, dual monitors, perhaps even a spare virtual machine that you could upload code to to run long-duration tests without blocking your main dev machine.
  • Reusable components - business logic, validation, UI components. No need to waste time re-inventing the wheel.
  • Knowledge transfer - like having a good, quick wiki, or technical/domain experts to trouble bottlenecks
  • Prevent and handle regression testing - such as code reviews to ensure higher quality code, as well as comprehensive suite of automated unit tests
  • Better automation - ideally you can automate anything tedious that steals your time, like checkouts, tests, code generation, continuous integration
  • Taking time to think first before coding - i.e. "code now, fix later" is more than just a moral killer, it also kills the schedule

There's a lot of things that are more standard, that I'd hope any developer would have:

  • Good source control system - no one wants to waste time because they lost their code, or had a merge error, or can't track something down
  • Issue manager system -
  • Good project management to coordinate the team and give everyone clearly defined goals.

There's obviously a lot more. What would make you a faster developer?

Tuesday, January 2, 2007

How Old is Legacy Code?

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/how_old_is_legacy_code.htm]

Most developers like to write their own, new exciting code. However, the reality is that often you deal not with new code, but rather existing "legacy" code. How old does code need to be before it's considered legacy? Some people say just a few minutes - you type code, you go get a snack, you come back, it's now legacy code. I don't think this is fully practical. Rather, here are some general guidelines that I personally find helpful in deciding if something is legacy code or not:

  • Is the original author no longer available? - Nothing makes code seem more legacy than when you no longer know who wrote it.
  • Is the code already in production? - Once code is in production, there is a definite contract and expectation that you need to adhere to.
  • Is the code to big to just throw away? - If the code is small enough that you can just throw it out and restart, it's not really legacy yet.
  • If it's your own code, have you forgotten it? - Even if you wrote the code yourself, if you've done several things since and therefore no longer remember it, it seems more legacy.

In summary, legacy code implies it's already in production, or it's too big to throw away, or you have to re-learn what the code does (because either the original author is gone, or you can't remember it). Throw-away code that you wrote five minutes ago which isn't used by anyone else isn't really legacy yet.