Soft Coding

« Return to Article
  • Ebs2002 2007-04-10 16:18
    I always cringe when OTHERS cringe about magic numbers. Sometimes, they're appropriate (as you're pointing out). What's the point of a mountain of defines or a config table that includes obvious information?

    #DEFINE NUM_DAYS_IN_WEEK 7
    #DEFINE ONE_MILLION 1000000
    #DEFINE NUM_SECONDS_IN_MINUTE 60

    Seriously, I think it's okay to use magic numbers in this case. I honestly don't see the need to have to change these any time soon. ("But Ebs2002, what would you do if the Pope decreed an eighth day of the week next year? You're captcha'd...er, I mean doom'd!" Yeah, so is everyone else in the world, and not because of broken software...)
  • Jeremy Stein 2007-04-10 16:19
    I completely agree. I think this is part of YAGNI. Incredible amounts of code complexity and indirection are added to otherwise straight forward software in the anticipation of never-realized changing requirements. Allowing flexibility where it is not needed is actually a *bad* thing. That never seems to be taught.
  • Justin Buist 2007-04-10 16:28
    Ebs2002:
    #DEFINE NUM_DAYS_IN_WEEK 7

    If you're counting from 0 it could be 6.
    Ebs2002:
    #DEFINE ONE_MILLION 1000000

    This prevents the developer from accidentally adding or removing a zero.
    Ebs2002:
    #DEFINE NUM_SECONDS_IN_MINUTE 60

    Reads easier, though I'd remove the NUM_ prefix.

  • akatherder 2007-04-10 16:28
    Yeah, you'll find me at the other end of the scale. I'm the lazy guy who hard codes everything possible and just wants to get the program up and running ASAP. I'm not going to spend my life writing my own little framework for every possible business rule change. If business rules change, then so should the code.

    Then I move on to the next project and leave the maintenance for the Junior Programmers. They are good at grepping now.
  • KattMan 2007-04-10 16:30
    Man this could end up as a big stink fest.

    If the examples were listed exactly as given they could be easy enough to implement without "soft-coding horror" and without "hard-coding" the values.

    You could have a states table that requires additional forms and a forms table that lists these forms. Easy enough to do and not to complicated to understand even when the code is there.

    ExcptStates = (query for state list)
    AdditionalDocs = (Query for docs)
    If (CurrentState in ExcptStates)
    Docs = Docs + AdditionalDocs;

    Seems easy and straight forward and if this were the only exception it would be a fine place to use soft-coded values.

    The problem comes up when you realize you have many different types of exceptions. So now you need an Exception table, with an ExceptionCheck table giving an ExceptionResult table, and somewhere in there you need a where to compare these exceptions.

    I can see how you could start with something simple and easily and rightfully so choose to make your check data driven only to later realize that continuing to follow that model when the checks become far more difficult actually does more harm than good.

    Ultimately, I see no problem when your rules are few and simple. If they are complex, go ahead and hard-code them into a single module that is your rules engine. This one library can than be enhanced when rules change without trying to track down where these changes need to be in a large application. This is what modular development and deployment is for, let's use it.
  • vt_mruhlin 2007-04-10 16:33
    My company has lots of "configuration" that just shouldn't be.
    The main configuration for our product is handled by a file called platform.ini. For my development box on our latest release, platform.ini is 1279 lines long.

    Customers found it too difficult to manage platform.ini, and customer service found it increasingly difficult to deal with customers who managed it themselves. So now we have a config generator. It takes a "smaller" config file, config.ini (931 lines), and runs it through a perl script which generates platform.ini based on an XML file, platform.xml (17049 lines). Try maintaining THAT.
  • SomeCoder 2007-04-10 16:37
    I like this article, Alex, but it almost seems like you're saying that we should never use configuration files/registry settings/database settings/whatever.

    I know that wasn't the spirit of the article but that's kind of what it sounded like.
  • VGR 2007-04-10 16:38
    As soon as I read the first paragraph, I knew I agreed with everything that was coming.

    It's just too much abstraction, serving no purpose. But I must say I like the term "soft coding" a lot. It's catchy.

    In general, programmers who are guilty of this have a more general problem: they only consider half of the effects of their approach. Does it do the job? Yes. Has anyone taken into consideration the amount of added complexity, and the future costs it will bring? Almost never.
  • TGnat 2007-04-10 16:38
    How about the encrypted config file filled with a dizzying array of soft-coded values...
  • vt_mruhlin 2007-04-10 16:40
    I forgot to mention. One of our components is based on 2 Finite State machines.

    The files that define the state tables are 700 lines long for one FSM and 1000-1400 for the other (depending on which protocol you use).

    These files are NOT to be touched by anybody but a developer, as the smallest of changes could break the whole system.

    Surely these files are compiled into the code you say. Nope, they're considered "config".
  • joe_bruin 2007-04-10 16:42
    Justin Buist:
    Ebs2002:
    #DEFINE NUM_DAYS_IN_WEEK 7

    If you're counting from 0 it could be 6.


    No, there are always seven days in a week.
  • ssprencel 2007-04-10 16:51
    SomeCoder:
    I like this article, Alex, but it almost seems like you're saying that we should never use configuration files/registry settings/database settings/whatever.

    I know that wasn't the spirit of the article but that's kind of what it sounded like.


    No. I think Alex is saying what I try to live my life by. "Everything in moderation." You don't want to hard-code everything and use magic numbers all the time but the opposite extreme is just as bad.

    I think the key to writing good code is to find a healthy balance between readability and performance.
  • qbolec 2007-04-10 16:55
    Well I believe that one should separate the business logic from the rest of the code.
    Say, like into separate *.cs files, or functions.

    I'm totally agreed with the article.
  • Sean 2007-04-10 16:56
    I don't think that constants for stuff like string literals is a bad thing.. ie stateCode == AZ where AZ = "AZ" somewhere else. Not because AZ reads better or "might change" but because it stops someone from accidentally saying stateCode == "Az" or some similar error.
  • Isuwen 2007-04-10 16:56
    If you want to see a good example of when soft coding is actually appropriate, take a look at the modern video game. Many offload game mechanics logic from the executable to a scripting language. It's still code; but it's code that can be changed without recompiling, and it's code that the end user can - and is even encouraged to - change!
  • Da' Man 2007-04-10 16:58
    Gee, people who didn't like neither soft nor hard coding invented... guess what: scripting!

    Captcha: alarm (that seems fair enough :-)
  • ElQuberto 2007-04-10 16:59
    Ebs2002:
    #DEFINE NUM_DAYS_IN_WEEK 7
    #DEFINE ONE_MILLION 1000000
    #DEFINE NUM_SECONDS_IN_MINUTE 60



    I like the num days in a week as that spells out to the person what you're trying to do -- otherwise they'll have to think "why do they have a 7 in there?"

    I've never seen the other two, maybe I'm lucky. I hard code 60 into my java code as usually I'm converting from milliseconds to minutes and it is obvious what I'm doing.
  • Redplague 2007-04-10 17:01
    The real WTF is that somebody withdrew their article. Who turns down their one chance at worldwide fame and fortune?
  • jonny lech 2007-04-10 17:01
    I'm inclined to disagree with this article. But maybe that's because what I work on really does have constantly shifting requirements where creating generic behaviors that are data driven...make sense.
  • qbolec 2007-04-10 17:03
    I've once worked for a company, where the Q&A complained about the use of 'magical constant' 0 in the for loop:
    "for(int i=0;i<something.size();++i)"
    When I asked them, what to they suggest, they insisted on:
    "const int FIRST_INDEX=0;"

    I tried to convince them, that once somebody release the compiler of C++ that counts from something other than 0, they will have larger problems that this, like for example the end of the loop condition won't be proper anymore.
    They agreed, and asked me to rewrite also this condition.

    Fortunately it was just a short internship, but I've learned a lot.
  • Zonkers 2007-04-10 17:08
    I used to do a lot of soft coding myself (love this term, btw) until I really got into language design concepts and ran across Greenspun's Tenth Rule. I believe that fundamentally, this is a statement against hard coding in general for the same reasons that you show.

    This is a great article.
  • mav 2007-04-10 17:08
    Hard coding values like 7 for days of the week or 60 for a number of seconds sucks when its down buried in some function and all you see is

    if( someVar % 7 == 1 )
    {
    // do stuff
    }

    I would much rather read:
    if( someVar % DAYS_IN_A_WEEK == TUESDAY)
    {
    // do stuff
    }

    Overall, this article didn't strike me as maintainable coding practice. If you always get rid of hard-coded values then you may have some things that are like, "well duh, that wasn't needed" but thats generally a lot better than, "what on earth does 7 mean?"
  • geoelectric 2007-04-10 17:09
    The biggest reason to separate stuff out into constants, readability aside, is DRY (Don't Repeat Yourself). If those form names and magic numbers and whatnot are only being used in one place, great. If not, then they should be consolidated into a constant so that if the string changes for any reason you only change it in one place.

    The other reason is documentation. Character codes, for example, should almost always be in a constant IMO. Sure, we're all rockstars and know that SPACE=32 and ENTER=13, but the next guy shouldn't have to.

    Otherwise, yeah.
  • Saladin 2007-04-10 17:16
    #DEFINE NUM_DAYS_IN_WEEK 7
    #DEFINE ONE_MILLION 1000000
    #DEFINE NUM_SECONDS_IN_MINUTE 60


    #DEFINE TRUE false
    #DEFINE FALSE true
  • Dwayne 2007-04-10 17:18
    mav:
    Hard coding values like 7 for days of the week or 60 for a number of seconds sucks when its down buried in some function and all you see is

    if( someVar % 7 == 1 )
    {
    // do stuff
    }

    I would much rather read:
    if( someVar % DAYS_IN_A_WEEK == TUESDAY)
    {
    // do stuff
    }

    That example has the added benefit of eliminating the ambiguity of whether Sunday or Monday starts the week.
  • Chris 2007-04-10 17:18
    The equation for the area of a circle is not subject to change. So that would be like a business rule that would be hard coded. Maybe which documents to attach or whatnot are not business rules but business variables. Worse are config files that aren't documented and then it's like the whole freaking app is one gigantic linear doomafalache.
  • Daid 2007-04-10 17:18
    mav:
    Hard coding values like 7 for days of the week or 60 for a number of seconds sucks when its down buried in some function and all you see is

    if( someVar % 7 == 1 )
    {
    // do stuff
    }

    I would much rather read:
    if( someVar % DAYS_IN_A_WEEK == TUESDAY)
    {
    // do stuff
    }
    Well, I would rather read:
    if( currentDay % 7 == 1) //We need to do magic on tuesday.
    {
    doMagic(number);
    }
    Or even better:
    if (getWeekDay(currentDay) == dayTuesday) //We need to do magic on tuesday, because tuesday is the international day of intergalactic magic.
    {
    doMagic(number);
    }

    Ok ok, the consts are also fine. Just illustating that there are multiple ways to get to Rome.
  • gerrr 2007-04-10 17:19
    Some people do take their anti-hard-coding bent too far.

    I have worked on programs where everything that would be a string literal or number in a formula is turned into a constant. It makes it ridiculously difficult to figure out what is going on because you have to constantly search and hunt for where the constants are defined. (because there are several hundred)

    Things that are only being used within a small scope, or only used once, usually do not need to be constants.

    The name of the page that a link goes to.. its used once, and now to figure out where I am navigating to, I have to go hunt down the 5 or so constants used to put the URL together.

    The name of a temporary file, that you are going to delete once you exit the scope of this loop.. you can declare a local variable.. no need to go off and make a #define in some other file mixed in with 100's of others.
  • RH 2007-04-10 17:28
    For me, hard coding is OK if it is for a very specific purpose (the two states with exceptions is a great example). AND IF IT IS DOCUMENTED ACCURATELY AND EFFECTIVELY.

    Also, there is a big difference between hard coding and duplicated hard coding. Let's say Texas stopped requiring that condition. If you need to go into 60 different places in your source to change that, then there's something wrong, and worse there is more of a chance of missing a 61st place where that condition is made, that could be a subtle bug that isn't easy to find.

    What I would have instead is a "Special76DocumentRequired()" function that would contain the "TX" or "AZ" condition, where it would be used wherever you needed. THAT is what maintainable and usable code is all about.
  • MRK 2007-04-10 17:29
    April Fools?
  • ObiWayneKenobi 2007-04-10 17:34
    So... the Real WTF™ is that today's actual article was withdrawn (WTF does that mean anyways? The submitter chickened out and decided not to have it posted?) and we got this stuff instead, right??
  • chrismcb 2007-04-10 17:36
    Ebs2002:
    I always cringe when OTHERS cringe about magic numbers. Sometimes, they're appropriate (as you're pointing out). What's the point of a mountain of defines or a config table that includes obvious information?

    #DEFINE NUM_DAYS_IN_WEEK 7
    #DEFINE ONE_MILLION 1000000
    #DEFINE NUM_SECONDS_IN_MINUTE 60

    Seriously, I think it's okay to use magic numbers in this case. I honestly don't see the need to have to change these any time soon. ("But Ebs2002, what would you do if the Pope decreed an eighth day of the week next year? You're captcha'd...er, I mean doom'd!" Yeah, so is everyone else in the world, and not because of broken software...)


    There are two reasons to use #define/enum/const whatever.
    One is the maintainability. But as you pointed out some numbers don't change. PI will also be 3.141... unless your legislature changes it. And then the the other reason kicks in, readability.

    Suppose you see value = time * 60. Is value in minutes? hours? Are we converting from seconds to minutes, or just get 60 times the number?

    One should never do #define ONEMILLION 1000000 Thats just plain stupid, ONEMILLION isn't any more informative than 1000000 (other than the lack of counting the 0s) ONEMILLION what? How about #define ARABIANNIGHTS 1000 or whatever value the 1000000 represents.

    We are all lazy and tend to hard code things. Thats one reason why buffer overrun possibilities exist.

    Pick meaningful names, and #define away your magic numbers. You may not care, but the guy who maintains your code after you will care.
  • Dennis 2007-04-10 17:39
    I like the style of this WTF. It's like a teacher, telling me what I should avoid and what are the pitfalls of software engineering. For a new, hobby and not even completely trained developer like me this is very useful.
  • mav 2007-04-10 17:41
    chrismcb:


    There are two reasons to use #define/enum/const whatever.
    One is the maintainability. But as you pointed out some numbers don't change. PI will also be 3.141... unless your legislature changes it. And then the the other reason kicks in, readability.

    Suppose you see value = time * 60. Is value in minutes? hours? Are we converting from seconds to minutes, or just get 60 times the number?

    One should never do #define ONEMILLION 1000000 Thats just plain stupid, ONEMILLION isn't any more informative than 1000000 (other than the lack of counting the 0s) ONEMILLION what? How about #define ARABIANNIGHTS 1000 or whatever value the 1000000 represents.

    We are all lazy and tend to hard code things. Thats one reason why buffer overrun possibilities exist.

    Pick meaningful names, and #define away your magic numbers. You may not care, but the guy who maintains your code after you will care.



    Huzzah! A smart person. Well put, sir.
  • chrismcb 2007-04-10 17:45
    WTF!!!!! I don't understand the point of the article? Are you suggesting we ship source code, and that when a change is made the user should make the change and recompile?


    Alex:

    private void attachSupplementalDocuments()
    {
    if (stateCode == "AZ" || stateCode == "TX") {
    //SR008-04X/I are always required in these states
    attachDocument("SR008-04X");
    attachDocument("SR008-04XI");
    }

    if (ledgerAmnt >= 500000) {
    //Ledger of 500K or more requires AUTHLDG-1A
    attachDocument("AUTHLDG-1A");
    }

    if (coInsuredCount >= 5 && orgStatusCode != "CORP") {
    //Non-CORP orgs with 5 or more co-ins require AUTHCNS-1A
    attachDocument("AUTHCNS-1A");
    }
    }

    I can already feel some of you cringing: Magic Numbers; String Literals; eww, that’s a lot of Hard Coding! However, not a single character in that example is Hard Coded: there is nothing that “shouldn’t be in source code” in the above code. The function simply implements a very clear and very specific business requirement with very clear and very specific code. Anything less and it would be Soft Coded.


    WTF? What do you mean "there is nothing that 'shouldn't be in source code'"? NONE of that should be in Source code.

    What happens when document SR008-04X changes to SR008-04Xa? What happens in AZ stops requirng SR008-04XI but requires SR008-04XT? What about in IL starts requirng SR008-04XI?
    What happens when inflation kicks in and the ledger amount threshold is 600K? BLAH BLAH BLAH

    Yeah you can't data drive everything. But you can't also hardcode everything either. And guess what, thats what our jobs are, to figure out the correct balance between the two.

    I kept reading this article, thinking you are showing off some WTF's. And maybe I missed the point and the whole thing was a ball of sarcasm. But really? WTF?
  • iToad 2007-04-10 17:47
    qbolec:
    I've once worked for a company, where the Q&A complained about the use of 'magical constant' 0 in the for loop:
    "for(int i=0;i<something.size();++i)"
    When I asked them, what to they suggest, they insisted on:
    "const int FIRST_INDEX=0;"

    I tried to convince them, that once somebody release the compiler of C++ that counts from something other than 0, they will have larger problems that this, like for example the end of the loop condition won't be proper anymore.
    They agreed, and asked me to rewrite also this condition.

    Fortunately it was just a short internship, but I've learned a lot.


    Among other things, you learned that you probably would be happier working somewhere else.
  • MRK 2007-04-10 17:48
    And thus the real WTF of this article was exposed. Since today is April 10, that would be April 1 in Big Endian notation. So April Fools to us all.
  • mav 2007-04-10 17:51
    MRK:
    And thus the real WTF of this article was exposed. Since today is April 10, that would be April 1 in Big Endian notation. So April Fools to us all.


    Oh snap. MRK gets plus 2 geek points.
  • bobday 2007-04-10 17:53
    chrismcb:

    What happens when document SR008-04X changes to SR008-04Xa? What happens in AZ stops requirng SR008-04XI but requires SR008-04XT? What about in IL starts requirng SR008-04XI?
    What happens when inflation kicks in and the ledger amount threshold is 600K? BLAH BLAH BLAH

    I imagine you'd change those values in the single place they appear.

    I'm sure any other way would involve extra work and leave you with less time to miss the point of new articles on this site.
  • mbvlist 2007-04-10 17:53
    In the Netherlands we have the 'belastingdienst' (something like 'Tax service'), which was like the IRS (but with a legal basis, unlike the USA ;)). Besides that there were dozen of other government organisations that all wanted money, or more common, give you money for some special occasion (65+, not fit for work, low wage etc). They had a beautiful hardcoded piece of software, that worked fine. Every 4 year after the elections some changes in the tax-rules would be applied, and we all lived happily ever after.

    Until some genius politician decided the 'Tax service' should also do social security and that kind of stuff. And the income tax rules were too difficult to understand, so they had to be changed. Since roughly 2000, every year the rules have changed. Typically the rules would be defined 20 december, driving all administrative software makers mad.

    But the one organisation suffering the most from these changes is the 'Tax service'. The software wasn't designed to be changed every year, let alone to do all tasks of about 10 organisations, so they can't keep up with the changes. People can't pay their daycare because the 'Tax service' can't process their change requests fast enough, people need to go to food banks while they have right at an income from the state, etc.

    At this moment nobody at the 'Tax service' stays longer than 6 months, they all flee away from the sinking ship. Unfortunately that means that nobody at their helpdesk has any clue what you should do with even the most basic cases, and IT performance degrading even faster. They are begging for a new system, but the politicians don't want to give it priority (because it costs too much, couple of billion euros)

    On the other hand, i've seen a demonstration of a generic tool for banks and such, where the rules were all typed in in some language by financial experts, with no changes at the code. Rules are stored in version management, enabling historical data to be recalculated using the old rules. Every customer of that system is delighted to get rid of the old monolithic system, and get a system in the place that can be changed on the fly (at least, that's what their representative at the University told ;)).
  • [ICR] 2007-04-10 17:55
    I feel perhaps it might be beneficial to point out that the article talks about moving constants and such like out from the code and into configuration files. It's perhaps a discussion that is more interesting than the tired hard coded vs. constant argument.

    Allowing the user to customise any and every constant in my experience leads to a lot of trouble. There is just too much scope to go wrong, and it's a nightmare helping someone who's configured something themselves.

    But of course you then have to find just the right defaults, and the right variables to allow configuration for and that's really difficult.
  • Marcin 2007-04-10 17:56
    The combination of brass neck, ignorance, and unsupported assertion present in this post qualifies Alex to become a programming and software guru. Well done Alex! The book and lecture circuit beckons!
  • MRK 2007-04-10 18:01
    Marcin:
    The combination of brass neck, ignorance, and unsupported assertion present in this post qualifies Alex to become a programming and software guru. Well done Alex! The book and lecture circuit beckons!


    Comedy Gold.
  • cparker 2007-04-10 18:09
    chrismcb:
    One should never do #define ONEMILLION 1000000 Thats just plain stupid, ONEMILLION isn't any more informative than 1000000 (other than the lack of counting the 0s) ONEMILLION what? How about #define ARABIANNIGHTS 1000 or whatever value the 1000000 represents.
    Following along with this example, I know the value for one million is universal, but what about for other numbers, where their names may not be? The value for my billion may not be the same as for your billion.

    One billion could equal either of the following:

    1 000 000 000
    1 000 000 000 000

    Conversely, 1 000 000 000 could be read as "one billion", "one thousand million", "one megamillion", or "one milliard".

    See also http://en.wikipedia.org/wiki/1000000000_%28number%29 for information on what I call "one billion".

    Having solid definitions of things like this--whether it be in configuration files or #defines--should be a requirement if you're writing a program that is going to be used--and developed--internationally.
  • sf 2007-04-10 18:09
    While I might agree it is possible to complicate you code with overly soft code, I think the examples go too far in the opposite direction. For example: what if customer A wants the ledger amount to exceed 5000 but customer B wants 6000? What if customer C wants document rev. "1B"? Are you going to maintain a code branch for every customer because these settings are hard-coded?

    The comment:
    "any more complicated than a simple, automated script that retrieves the code from source control, compiles it, copies/installs the executables, and then runs the relevant database scripts."

    implies a company IT department to me, where the developers have one customer, the company, and they own the deployment environments. In this situation you may be able to get away with this level of hard-coded rules and settings (barely).
  • gkdada 2007-04-10 18:12
    The reason to use "#define NUM_DAYS_IN_WEEK 7" is not because the the number of days in a week may change. Rather it is to show (in the code) that the reason you are multiplying (or dividing) something with 7 is BECAUSE there are seven days in a week. Same thing goes for third one as well. I don't see much reason for the second one, though (as someone pointed out) it may be to avoid the mistake of adding or missing a zero.
  • AGould 2007-04-10 18:12
    #DEFINE NUM_DAYS_IN_WEEK 7
    #DEFINE ONE_MILLION 1000000
    #DEFINE NUM_SECONDS_IN_MINUTE 60


    When I see those, my first thought is "the variables must be poorly named". If I need SECONDS_IN_MINUTE to understand:

    randomFoo = someBar * SECONDS_IN_MINUTE

    it's time to rewrite to

    secondsToDestruction = minutesOnClock * 60
  • Doug 2007-04-10 18:13
    I have been accused of being a Complicator (http://worsethanfailure.com/Articles/The_Complicator_0x27_s_Gloves.aspx). So I did cringe at first. But look again at this code:

    Alex:

    private void attachSupplementalDocuments()
    {
    if (stateCode == "AZ" || stateCode == "TX") {
    //SR008-04X/I are always required in these states
    attachDocument("SR008-04X");
    attachDocument("SR008-04XI");
    }

    if (ledgerAmnt >= 500000) {
    //Ledger of 500K or more requires AUTHLDG-1A
    attachDocument("AUTHLDG-1A");
    }

    if (coInsuredCount >= 5 && orgStatusCode != "CORP") {
    //Non-CORP orgs with 5 or more co-ins require AUTHCNS-1A
    attachDocument("AUTHCNS-1A");
    }
    }


    Notice that this is a function. So chrismcb, in answer to you questions:

    chrismcb:

    What happens when document SR008-04X changes to SR008-04Xa? What happens in AZ stops requirng SR008-04XI but requires SR008-04XT? What about in IL starts requirng SR008-04XI?
    What happens when inflation kicks in and the ledger amount threshold is 600K? BLAH BLAH BLAH


    You look through the code, find a call to this function, change this function once with the new requirements, and the "bug" is fixed no matter how many places from which this is called.

    And as far as recompiling goes, well it depends on how you have structured things. If it is ONE-BIG-MONOLITH, yes it all gets recompiled. It also does if you have ONE-BIG-MAGIC-NUMBER-FILE. If it is distinct little pieces linked dynamically in memory, maybe there is less recompiling. If it is all in the database, maybe nothing is recompiled. But maybe it's mental gymnastics and a few strained neurons.

    Nothing is perfect. Not even our code. Especially our code. Oh, well ...
  • RaspenJho 2007-04-10 18:14
    Someone had to do it....

    (written in notepad)


    <SUPPLEMENTAL_DOCUMENTS>
    <CONDITION TYPE="stateCode" VALUE="AZ" OPERATION="=">
    <ATTACH DOCUMENT="SR008-04X" />
    <ATTACH DOCUMENT="SR008-04XI" />
    </CONDITION>

    <CONDITION TYPE="stateCode" VALUE="TX" OPERATION="=">
    <ATTACH DOCUMENT="SR008-04X" />
    <ATTACH DOCUMENT="SR008-04XI" />
    </CONDITION>

    <CONDITION TYPE="ledgerAmnt" VALUE="500000" OPERATION=">=">
    <ATTACH DOCUMENT="AUTHLDG-1A" />
    </CONDITION>

    <MULTICONDITION>
    <CONDITIONS OPERATION="AND">
    <CONDITION TYPE="coInsuredCount" VALUE="5" OPERATION=">=" />
    <CONDITION TYPE="orgStatusCode" VALUE="CORP" OPERATION="!=" />
    </CONDITIONS>
    <ATTACHMENTS>
    <ATTACH DOCUMENT="AUTHCNS-1A" />
    </ATTACHMENTS>
    </MULTICONDITION>
    </SUPPLEMENTAL_DOCUMENTS>

    private DocumentRules LoadSupplementalDocumentRules()
    {
    /* ... Load above configuration ... */
    }
    private void AttachDocuments(Document[] docs)
    {
    /* ... Attach documents ... */
    }

    private void AttachSupplementalDocuments()
    {
    DocumentRules rules = LoadSupplementalDocumentRules();

    foreach(Rule rule in rules)
    {
    Document[] docs = EvaluateRules(rule);

    if (docs != null)
    {
    AttachDocuments(docs);
    }
    }
    }

    private Document EvaluateRules(Rule rule, DataObject data)
    {
    Condition cond = rule.Condition;
    MultiCondition mc = cond as MultiCondition;
    Document result = null;

    if (mc == null)
    {
    // Rule is not compound. Simple evaluation.
    result = EvaluateCondition(cond, data) ? cond.Documents : null;
    }
    else
    {
    // Rule is compound. Complex evaluation.
    if (mc.MultiConditionOperation == MultiConditionOperation.And)
    {
    result =
    EvaluateCondition(mc.Condition1, data) &&
    EvaluateCondition(mc.Condition2, data) ?
    cond.Documents :
    null;
    }
    else
    {
    result =
    EvaluateCondition(mc.Condition1, data) ||
    EvaluateCondition(mc.Condition2, data) ?
    cond.Documents :
    null;
    }
    }

    return result;
    }

    private bool EvaluateCondition(Condition cond, DataObject data)
    {
    object value =
    cond.Type == "stateCode" ? data.StateCode :
    cond.Type == "ledgerAmnt" ? data.LedgerAmnt :
    cond.Type == "coInsuredCount" ? data.CoInsuredCount :
    cond.Type == "orgStatusCode" ? data.OrgStatusCode :
    string.Empty;

    return
    ( (cond.Operation == Operation.EqualTo && value == cond.Value) ||
    (cond.Operation == Operation.NotEqualTo && value != cond.Value) ||
    (cond.Operation == Operation.LessThan && value < cond.Value) ||
    (cond.Operation == Operation.GreaterThan && value > cond.Value) ||
    (cond.Operation == Operation.LessThanOrEqualTo && value <= cond.Value) ||
    (cond.Operation == Operation.GreaterThanOrEqualTo && value >= cond.Value) ||
    (cond.Operation == Operation.IsNull && value == null ) ||
    (cond.Operation == Operation.IsNotNull && value != null )
    );
    }


    Addendum (2007-04-10 18:25):
    AttachSupplementalDocuments should accept a DataObject and pass it to the EvaluateRules method.

    Addendum (2007-04-10 19:02):
    Found another WTF in my Notepad# code...

    result =
    EvaluateCondition(mc.Condition1, data) &&
    EvaluateCondition(mc.Condition2, data) ?
    cond.Documents :
    null;

    should be

    result =
    (EvaluateCondition(mc.Condition1, data) &&
    EvaluateCondition(mc.Condition2, data)) ?
    cond.Documents :
    null;
  • Mr Steve 2007-04-10 18:16
    This article really gets to the heart of 'art of coding', that is finding the right balance between:

    saving time and money now (hard coding)

    vs

    saving time and money later (soft coding)


    for whatever weird reason, coders generally think in terms of soft coding and making great frameworks that will change the world! (just look at how many ajax frameworks and javascript form frameworks there are currently out there).

    that's only one side of the art

    people (publicly at least) say they dislike hard coding and hacks. personally i think that they're great. alot of the code that you currently write is for products that have a half life of less then 2 years. often there's no reason to abstract the hell out of your code cos your product will get binned and replaced, so your abstraction is simply a waste of time and energy.

    so it's important to be mindful of this and go for balance.
  • Marcin 2007-04-10 18:17
    MRK:
    Marcin:
    The combination of brass neck, ignorance, and unsupported assertion present in this post qualifies Alex to become a programming and software guru. Well done Alex! The book and lecture circuit beckons!


    Comedy Gold.

    Who's joking?
  • Chris 2007-04-10 18:20
    I've found that soft coding can be advantageous if your compiled application will be deployed to multiple locales, such as to the US and Canada. Sure, you can hardcode the number of seconds in a minute, but it's more costly to change hardcoded dollar thresholds and interface text for each locale.

    Maintaining configurations for each locale might be easier than forking the codebase in these situations.
  • Cotillion 2007-04-10 18:39
    chrismcb:
    Pick meaningful names, and #define away your magic numbers. You may not care, but the guy who maintains your code after you will care.

    Always program as if the person who will be maintaining your program is a violent psychopath that knows where you live.
  • phs3 2007-04-10 18:41
    After having been through the hassles of renaming products, changing company ownership, etc., I know a developer who made both the product AND the vendor name configurable in the product configuration file...

    ...phsiii
  • Zygo 2007-04-10 18:43
    It’s a pretty silly fear to have. The whole point of software (hence, the “soft”) is that it can change that it will change. The only way to insulate your software from business rule changes is to build a completely generic program that’s devoid of all business rules yet can implement any rule. Oh, and they’ve already built that tool. It’s called C++. And Java. And C#. And Basic. And, dare I say, COBOL.


    Uh, no, it's called Tcl. And Perl. And Ruby. And PHP. And, dare I say, LISP.

    Systems implemented in compiled languages generally can't read data from a database, network socket, config file, etc. and execute the data directly (at least not without jumping though some fairly complex hoops, and certainly not within a loop). Scripting languages, on the other hand, do this with ease.

    Let's play a game. Let's implement all the variable business logic rules in Some Random Scripting Language (SRSL), by providing all the required objects, accessors and mutators on all your objects where the SRSL code can get to them. You could even put the SRSL code into the database, so it can be edited in the field. The fixed application code now looks like:


    String srslCode = executeSqlQuery("SELECT srslcode FROM config WHERE srslprocname = 'attachSupplementalDocuments'");
    SRSLExecute(srslCode);


    where srslCode looks like


    if {$stateCode == "AZ" || $stateCode == "TX"} {
    # SR008-04X/I are always required in these states
    attachDocument "SR008-04X"
    attachDocument "SR008-04XI"
    }

    if {$ledgerAmnt >= 500000} {
    # Ledger of 500K or more requires AUTHLDG-1A
    attachDocument "AUTHLDG-1A"
    }

    if {$coInsuredCount >= 5 && $orgStatusCode != "CORP"} {
    # Non-CORP orgs with 5 or more co-ins require AUTHCNS-1A
    attachDocument "AUTHCNS-1A"
    }


    So now our hypothetical application is executing the SQL query and running the SRSL interpreter over the code that comes back when the application gets to the point where it's attaching supplemental documents. Business rules are implemented in SRSL, which is editable by sufficiently trained users with appropriate access to the data. But wait, you maybe want this flexibility in other parts of the process, not just supplemental document attachment. Maybe you want additional variables too. So write the part of the system that calls attachSupplementalDocuments in SRSL too. And the parts that get data from the database. And the parts that update the database. And the parts that interact with the user. And the part that creates whatever container the documents are being attached to. And the part that calls the part that calls attachSupplementalDocuments.

    Eventually this little game ends when the entire application (except maybe for some highly specialized processing, like image compression or PDF generation, and the "main" function) is written in SRSL. And that is most likely what SRSL was designed for in the first place, so that's OK. We see this pattern all the time, in PHP, Javascript, SQL, Tcl, LISP, etc. It's nothing to be ashamed of, and in many cases it's industry standard best current practice.

    Now that we've finally achieved what we wanted--business logic specified by data at runtime, separated from the application core code--notice that the SRSL "configuration data" is full of hard-coded constants and fixed business logic, it can't be maintained by anyone who isn't a software developer, deployment is either really easy or really hard depending on what architecture and technology choices you made, and if the user has any kind of problem with it the average help desk droid is going to be useless to help them. In fact, you could probably "optimize" it by translating it into some kind of compiled language...

    Anyone who's been through this loop once (in either direction) knows what the first step feeks like, and either skips immediately to the logical end of the process, or decides to get on with their life and writes the code in whatever language they started with. It's only people who are going through this process for the first time that don't realize that the logical end of the process is always exactly identical to the beginning, and that either end is preferable to being stranded somewhere in between.
  • ifthenelse 2007-04-10 18:53
    qbolec:
    I've once worked for a company, where the Q&A complained about the use of 'magical constant' 0 in the for loop:
    "for(int i=0;i<something.size();++i)"
    When I asked them, what to they suggest, they insisted on:
    "const int FIRST_INDEX=0;"

    I tried to convince them, that once somebody release the compiler of C++ that counts from something other than 0, they will have larger problems that this, like for example the end of the loop condition won't be proper anymore.
    They agreed, and asked me to rewrite also this condition.

    Fortunately it was just a short internship, but I've learned a lot.


    Uh, what you should have been using is an iterator and avoided the problem altogether.

    In pseudo-code cause I don't have all the information:

    something_type::iterator itr = something.begin();
    
    for (; itr != something.end(); itr++)

    Or "++itr" if you prefer, I hate that syntax. Yes I know the risks.
  • chrismcb 2007-04-10 18:53
    Doug:

    You look through the code, find a call to this function, change this function once with the new requirements, and the "bug" is fixed no matter how many places from which this is called.

    And as far as recompiling goes, well it depends on how you have structured things. If it is ONE-BIG-MONOLITH, yes it all gets recompiled. It also does if you have ONE-BIG-MAGIC-NUMBER-FILE. If it is distinct little pieces linked dynamically in memory, maybe there is less recompiling. If it is all in the database, maybe nothing is recompiled. But maybe it's mental gymnastics and a few strained neurons.

    Nothing is perfect. Not even our code. Especially our code. Oh, well ...


    Nothing is perfect, but teaching flawed patterns doesn't strive for perfection.

    Yeah there is an argument between changing the code vs changing the data. And for something its 6 of one, half dozen of the other. But this example isn't one of those.

    Lets suppose, instead of just having two states with odd forms, you have 50 states. What would you rather maintain a table, or a bunch of if statements?

    What is easier to deploy, a new set of dlls or a new database file?

    What is easier to test a new dll or a new database file?

    What is easier for the customer? Update thier data, or wait for the vendor to release the new version (of course releasing the new version may mean more money, and maybe thats the reason for this sloppy coding practice?)

    An now what happens when you need to run something for year 2006 vs 2007? You can take old buggy version of the app built in 2006, and live with the bugs. Or you can take the newer cleaner less buggy 2007 version and plug in the 2006 data.

    Decouple your data as much as possible. Sure it isn't always possible, or prudent. Sometimes it is easier for everyone to bake stuff into the app (again thats our job). I just think that the example given is a PRIME example of something that shouldn't be in the code, despite the article claiming otherwise.
  • Zygo 2007-04-10 19:04
    chrismcb:
    What happens when document SR008-04X changes to SR008-04Xa? What happens in AZ stops requirng SR008-04XI but requires SR008-04XT? What about in IL starts requirng SR008-04XI?
    What happens when inflation kicks in and the ledger amount threshold is 600K? BLAH BLAH BLAH


    Assuming the Once and Only Once rule is followed, you go edit that function and make exactly those changes to the code. If OaOO is not followed, you're screwed, hard or soft coding doesn't matter.

    The common case for software development is software with a very small number of developers and users (typically one of each, and each one is part of a single corporate entity). Often the developer is also the administrator and support, so it comes down to "IT will change config file "xyz.cfg" variable "foo" to "SR008-04XI" or "IT will edit attachSupplementalDocuments.cc, rebuild, and install." Either way, IT's doing the work, so it makes no sense for IT to pretend that anyone else can, or do a lot of extra work to implement a framework that allows their job to be done by someone else, in theory, if they had the same skill set and training and a detailed operational knowledge of the system.
  • arty 2007-04-10 19:11
    phs3:
    After having been through the hassles of renaming products, changing company ownership, etc., I know a developer who made both the product AND the vendor name configurable in the product configuration file...

    ...phsiii


    Not only because the company changes hands. Sometimes you can only make a sale if another company can brand your product. This is what things like the IE resource kit are for.
  • Morgan 2007-04-10 19:15
    Greetings,
    (heavily truncated from my original response)

    Maybe I'm misreading this, but I've been at many companies where DSLs were necessary, so I can't agree.

    'Just do another build and deploy' (to paraphrase) is absurdly simplistic. Infuriatingly so, in fact, to the point where I have to suppress the urge to insult whomever thinks that building (oh, and MAYBE some database scripts) is all there is to a deploy. For example, there's QA, downtime, perf tests, documentation, multiple servers, digital signatures, at the LEAST, and then there's the whole world of software development which ISN'T confined to a server entirely under your control.

    Just wait until Florida starts requiring SR008-04X/I, and you have to push the new code to 25,000 users who've already downloaded the 47MB app once from your site (or maybe BOUGHT THE CD). Wouldn't it be nicer to push a 10k business-rules script file update that didn't require an uninstall and reinstall?

    Even for web apps, taking downtime and pushing a full binary build to a hundred servers just to add a new state code is just wrong. (Sure, if you're one guy, with one webserver, who the f...*cough* heck cares, but that's not the entire world of software development.)

    Given the tendency for programmers to egregiously hardcode values that REALLY should be configurable, suggesting that behavior is permissible is a poor optimization. Balance is critical, don't go overboard, but for goodness sake, PLEASE don't encourage people to hard-code things!

    Sure, you rarely start off with a whole DSL, but when you get frustrated with the rate of change, and the process surrounding change, you need one. When you decide you need one, 'soft-coding' be damned.

    If we ever get to the point where soft-coding is a greater problem than hard-coding, I'll rejoice, because that's a GREAT problem to have in comparison to the train-wreck of hard coding that is far more common in software development.

    This feels like someone who recognizes the train wreck that is Hibernate and Spring configuration (and similar technologies), and yet has had their hand slapped for hard coding, and is trying to come up with a justification for it.

    Just don't do it.

    -- Morgan
  • Dustin 2007-04-10 19:33
    One specific goal of not Hard Coding is to improve consistancy. If you have:

    if (ledgerAmnt >= 500000) {
    //some code...
    }

    In dozens of places, and next year it becomes 650000, changing a single constant would be a lot safer, particularly if you have other code that just happens to use 500000:

    if (balanceSheetAmnt >= 500000) {
    //Balance Sheet of 500K or more requires AUTHLDG-2C
    attachDocument("AUTHLDG-2C");
    }
  • Chris 2007-04-10 19:41
    Just remember the three main tiers:

    Presentation
    Logic Flow
    Data

    Keep those separate in your system. Presentation should be handled by some sort of designer. Data is handled by a data source that's (mostly) de-coupled from the program - which is why databases were invented. The logic flow is obviously implemented with programming languages. So if you need to change the logic, you HAVE to change the program. It's pretty irrational to believe that you don't have to recode anything if some form of logic changes.

    Don't confuse "soft-coding" for configuration. Configuration is merely a change of data (so things like dollar thresholds, etc), but trying to make your program's logic work differently through configuration is what he means by "soft-coding".
  • tieTYT 2007-04-10 20:00
    Morgan:
    Greetings,
    'Just do another build and deploy' (to paraphrase) is absurdly simplistic.


    Mod parent up... oh wait this isn't slashdot.
  • OSE 2007-04-10 20:14
    What a retarded rant. What do you have against DSLs anyway? They're not always appropriate nor the best solution, but for those times when you need them, they beat everything else hands down.

    If your business rules change frequently (especially for an internal process) then DSLs are awesome. If they change infrequently and must be QA'ed to absolute death, then straight Java (or whatever) is probably better. If you have something in between, figure out what works given your requirements.

    There isn't a religious discussion here. Magic numbers in code are bad, period, since if they're magic they carry meaning beyond the context they appear in. Indirection for its own sake is also bad. Stop trying to push the issue some other way.
  • Ed 2007-04-10 20:21
    What about the dreaded Change Control Policy?? That tends to make rolling out the code changes a bit of a headache.
  • m23 2007-04-10 20:27
    chrismcb:
    WTF!!!!! I don't understand the point of the article? Are you suggesting we ship source code, and that when a change is made the user should make the change and recompile?


    <sarcasm>
    Of course not...

    You use Perl. Then they don't need to recompile.
    </sarcasm>
  • Bell Endian 2007-04-10 20:30
    MRK:
    And thus the real WTF of this article was exposed. Since today is April 10, that would be April 1 in Big Endian notation. So April Fools to us all.


    Rubbish. I would bet my wife that Alex used an big-endian computer to publish this submission, on which basis, 1 is 1 and 10 is 10 in big endian notation.

    Now if you meant *little-endian* notation, then we have to ask some questions. if you're just talking about the day ordinal, and working on a 32 bit platform, then 1 is 01000000 and 10 is 0a000000 in little endian notation, the values 16777216 and 167772160 respectively. Even mod 30 (or should that be NUM_DAYS_IN_SEP_APR_JUN_AND_NOV?) that's Apr 14th, and funnily enough, 10th respectively. Now let's factor in the rest of the date. How are we going to store the date? in milliseconds since Jan 1 1970? (or if you're using SQL Server 2000, milliseconds since Jan 1 1900 - yeah, nice one), in julian date format?

    For the sake of brevity, let's just agree that 10 is never 1 in the opposite endianness. well, not in any microprocessor ever built anyway.

    CAPTCHA: gotcha
  • Zonkers 2007-04-10 20:41
    mbvlist:
    Until some genius politician decided the 'Tax service' should also do social security and that kind of stuff. And the income tax rules were too difficult to understand, so they had to be changed. Since roughly 2000, every year the rules have changed. Typically the rules would be defined 20 december, driving all administrative software makers mad.


    I'm sure that this is something that soft-coding wouldn't help fix much. This is a major addition/change of functionality.

    On the other hand, i've seen a demonstration of a generic tool for banks and such, where the rules were all typed in in some language by financial experts, with no changes at the code.


    A system like this always sounds great but I've never seen a system like this actually work in practice like is states. Usually what you end up with is that there is a small team of specialists that are able to code in this new "language" (see Greenspun's Tenth rule, that I referenced in an earlier post here).

    As a former specialist myself of such a system that was supposedly so easy to use via it's GUI that even as a specialist in the system (and a programmer), I had so much trouble actually getting it to do what I needed it to do. The system was a real pain and I would dare anyone not technically versed in the logic that its supposedly hides from the user to actually be able to use it properly. Basically to be able to use it you not only had to know basic programming concepts but you also need to know the quirky "language" of the system. That what this sounds like to me, even though they may claim that these people just need to be financial experts, then the rest is easy right? right? To me, that's spoken like a programmer who helped build the system and already knows programming like it is second nature. Sure, it's easy for that guy, but try giving it to some guy in finance.
  • Sixtus Freebyte 2007-04-10 20:45
    The problem on "soft coding" is that you will create a language beside the language, a compiler beside the compiler and tools beside the tools in the near future because you are afraid of side effects to your core which *should* be avoided by creating an interface and a separate configuration language.

    Solutions:

    - either build a core providing services and write everything in your own control language (thats the way SAP and other large companies are going)

    - or create interfaces where you can do your own coding in an arbitrary procedural or OOP language ("plugin style")

    - or do it the Lisp way and eval() everything.

    I have to maintain a lot of business applications and I'm not very pleased to remember all the bugs and syntax problems the "official retrieving languages" (like SQL), homegrown "[%if $this.eq($that)%]"-moveproblemsoutofthecore and stuff like "plain text on steroides" (<xml>) have.

    For one of my latest applications I simply created interfaces to Java where the compiler is free and the syntax is almost understandable (the application is a great success).

    (captcha: smile - yea, I do) Sixtus

    Sixtus
  • Stephen Touset 2007-04-10 20:47
    chrismcb:
    PI will also be 3.141... unless your legislature changes it.


    This comment alone demonstrates why we should gravitate towards using constants for this sort of thing, as opposed to typing the number in.

    No, the value of Pi will not change. But business requirements for its precision might. We may start out with 3.141 and find out two months from now that our precision requirements dictate more significant digits. So now we've got to do a "s/3.14/3.14159/g" on the whole codebase to change the precision. The same thing happens in reverse a few months farther down the line, and here we go again.
  • kanna 2007-04-10 21:18
    I came out of school with a... non practical programming education, learned everything I could at my first job, went on to become an independent contractor, and realized a lot of what I had learned was really crap. I spoke to my old "mentor" and he said "yeah, I was learning too when I wrote that".

    The only way to solve the issue is to separate as much as you can, and comment. I really think saying

    #define NUM_SECS_IN_MIN 60

    (pardon my C) is a little ridiculous. Put a 60 in the code and comment it.

    Also, being in a position where I maintain code that does things I never dreamed of having to learn, I've come to realize that it's really important to understand what the code is doing without looking at the code. If your code handles a lot of formulas, it's important to know the formulas themselves before you can really understand what the code is doing. I'm the "programmer" in my job, but I find myself CONSTANTLY going back to the subject matter experts to learn the formulas so I can verify the code. The intent of the code is to do the formulas, the formulas won't change (often)... so when I learn the formulas, I know why that 42 is there and what it means.

    I realize not everyone has a subject matter expert to look to... in those cases, the biggest complaint should be the lack of documentation. In the case of figuring out if time/60 is seconds to minutes or minutes to hours, the fault is in the variable name. Time isn't exactly the best call... maybe tSeconds or tMinutes (if you're into Hungarian Notation) or just seconds or minutes would be a MITE bit better. Remember, name the variables what the mean, not what they are.

    As for "having to change the code in 60 places" try a little Object Orientation. Create a function or sub, name it appropriately (Seconds_to_Minutes) and drive on. If it's a check you may need to do more than once, try a function there too, especially if it's a business rules check. This way you only need to change the one function... even if it's just

    Boolean Check_AZ_TX(string stateCode)
    {
    if (stateCode == "AZ" || stateCode == "TX") return true;
    else return false;
    }


    And when you realize the documentation is non-existent and it's going to take you three times as long to figure out the code, let your manager know what's up, explain to her/him the need for documentation, suck it up and start writing documentation. I'm a programmer, I hate writing documentation as much as anyone, but it's necessary. I realize it's necessary for the next poor sap as much as it is for me when, two years later, I'm asked to maintain code that I've long sinced flushed out of my memory.

    There are tools and well established practices for dealing with this situation. Time spent on a solid design, time spent thinking a little ahead, and time spent refactoring code as you go along is time well spent. Time spent documenting is solid gold.
  • Therac-25 2007-04-10 21:37
    These discussions about date constants are rather odd -- does anyone still do date math themselves? Aren't there solid date and time libraries in every language? I haven't used anything except Date::Manip in Perl and the forest of inheritance trees of objects in Java to do this stuff since I was bitten the first time (there are at least two days in the year (in my locale) that aren't 86400 seconds long....)

    Also, the description of the business rule system is amusing -- I'm working on a project right now where there's alot of pressure to go that route ("I do not want to change code."). I proposed that we store a part of the logic as Scheme and eval it with JScheme after pulling it out of the database. Let's hope that the idea catches on.
  • tster 2007-04-10 21:45
    joe_bruin:
    Justin Buist:
    Ebs2002:
    #DEFINE NUM_DAYS_IN_WEEK 7

    If you're counting from 0 it could be 6.


    No, there are always seven days in a week.


    wrong, There are 7 days in a week if you are using a calendar that specifies that there are 7 days in a week. Indeed, calendars besides Gregorian calendar exist.



    What happens when document SR008-04X changes to SR008-04Xa? What happens in AZ stops requirng SR008-04XI but requires SR008-04XT? What about in IL starts requirng SR008-04XI?
    What happens when inflation kicks in and the ledger amount threshold is 600K? BLAH BLAH BLAH


    I imagine you'd change those values in the single place they appear.

    I'm sure any other way would involve extra work and leave you with less time to miss the point of new articles on this site.


    also wrong. To change something in the source code at many organizations means to push out a new build of the application. This new build has to be put through sanity tests because if a customer receives a build from us and then looks at our database of test results and sees that we didn't run any tests against the build we gave them they might shit themselves.
  • Therac-25 2007-04-10 21:51
    Oh yeah, this was covered 26 years ago:

    The only way to implement an extensible system using an unsuitable language, is to write an interpreter for a suitable language and then use that one. -- rms, 1981
  • tster 2007-04-10 22:01
    kanna:


    #define NUM_SECS_IN_MIN 60

    (pardon my C) is a little ridiculous. Put a 60 in the code and comment it.


    you could put a 60 and then comment it... or you could put a SECONDS_PER_MINUTE and not put any comments because the code is completely obvious. Take your pick, but there is a right answer here.

    kanna:

    As for "having to change the code in 60 places" try a little Object Orientation. Create a function or sub, name it appropriately (Seconds_to_Minutes) and drive on. If it's a check you may need to do more than once, try a function there too, especially if it's a business rules check. This way you only need to change the one function... even if it's just

    Boolean Check_AZ_TX(string stateCode)
    {
    if (stateCode == "AZ" || stateCode == "TX") return true;
    else return false;
    }



    First off, this isn't object orientation and it has nothing to do with it. Secondly, I can only hope and pray that you aren't serious.

    1. If you are going down this road you have set yourself up for MASSIVE code duplication. If you don't want code duplication you can do the following:

    boolean check_TX_AZ(String state)
    {
    return(check_TX(state) || check_AZ(state));
    }

    otherwise you can end up having duplicated code literally hundreds of times. Secondly, unless you are writing in a dynamic language and creating these function on the fly, this is perhaps the worst idea you can have. The next thing you know you'll have a multi thousand line source code file filled with every possible check you can think of. To make a change in the actual business logic you will have to open the file and search it for the function you are looking for, if it doesn't exist create it, blah blah blah.

    much better is to have a file with #define or const or preferably an enum or whatever of all 50 states. Then you use the 50 constants so that you get at least a little bit of type checking.
  • eyrieowl 2007-04-10 23:12
    i think a lot of other people have raised most of the salient points about why soft-coding makes sense for certain tasks. but i couldn't not say this: a poor implementation of an idea is no reason whatsoever to dismiss the idea. it seems to me that a lot of alex's argument rests on his (i'm sure well-founded) dislike for the rules engine he was exposed to. but just because someone was able to do it badly doesn't inherently mean it shouldn't be done.

    one of the most important (in the learn-a-lot sense) projects i had in college was to develop an application for filling out the previous year's IRS form 1040, along with a few associated worksheets. nothing fancy, not laden with all the intricacies of the tax-code, but, not entirely trivial either. the one other requirement was that after finishing, we had to swap our code with another team and make the necessary changes to automate the current year's 1040. we got a D, which sucked, after spending some considerable quantity of time writing a bunch of code (which we tried really hard to make pluggable) with all the rules from the 1040. but it was still a pita for the next team, and we had no illusions about it. we simply hadn't even *thought* about the correct solution, which was to come up with a nice little form (xml works well as an encoding for this, but anything would have done) with the fields and relationships on the 1040. that is _the_ correct solution, and i have not a shred of doubt about it. externalizing that logic could still be done very poorly, but that does not mean that it shouldn't and couldn't be done, and done well.
  • Hardy 2007-04-10 23:38
    qbolec:
    I've once worked for a company, where the Q&A complained about the use of 'magical constant' 0 in the for loop:


    As if your QA dept actually looks at code!?
  • amonynous cow 2007-04-10 23:43

    If you're counting from 0 it could be 6.

    LAST_DAY_OF_WEEK could be 6 or 7, but the # of days in the week is 7 no matter what. Unless you're in some other type of calendar...
  • AN 2007-04-10 23:55
    You know, we are so far down the road of soft coding that it would blow your mind, and it works for us. We have a couple of dozen clients, and they all have custom data, different versions of forms, and different business logic. We don't have massive code forks for these clients, we just configure the bejeezus out of the application.

    Our ORM model is configurable. Our business logic is configurable. Our presentation model is configurable. All of this is runtime loadable, and we edit the configuration data with more or less the same tools that our clients use to edit *their* data. We store all the data in the database, right alongside the application data.

    Yes, there are serious risks and problems associated with this methodology. But given our scenarios, the alternatives are worse. And by maintaining configuration metadata for everything, we can support both a Windows desktop client and a web client without coding all our customizations twice. And when a client asks for another label to be changed and for more alterations to the process flow, it doesn't require us to mess with the overall source tree and we don't have to go through a complicated deployment process -- we don't even have to recompile!

    The moral of the story: badly-thought-out softcoding is bad. But badly-thought-out *anything* is bad. Don't be afraid to use advanced, potentially-messy techniques in your code base. But only use them if they make sense for your situation, and prepare yourself for the landmines that come with that approach.
  • Tony 2007-04-11 00:17
    I *mostly* agree with the article... I have one caveat, though:

    If you've got a whole bunch of files... say, 250 different Cold Fusion files for a website, and each one of them has buried in it somewhere:

    <div id="#theQuery.thingIWantToDisplay#"></div>

    then I can either leave it looking like that, or I can abstract it out to the following:

    <div id="#THING#"></div>

    and add <cfset THING = theQuery.thingIWantToDisplay> ONCE in the Application.cfm file, which gets included at the top of every page on the site.

    That way, if THING changes (and it will... remember Murphy's Laws of Computing) I can change it in ONE place. If I have to change it in 250 places, I can guarantee that I'll miss some of them. Therefore, I try to make sure my code has the fewest number of moving parts possible.

    That having been said, I know the dangers of soft coding, as I've spent some time banging my head against the wall back when I worked in a classic ASP shop with the following:

    function functionName
    //do some stuff here
    returnValue = VARIABLE_DEFINED_ELSEWHERE
    end function

    "F***! Now I get to go looking through eleventy billion include files praying to God I'll stumble on the one where VARIABLE_DEFINED_ELSEWHERE is defined..."
  • Jonathan Allrn 2007-04-11 00:27
    Mr Steve:
    This article really gets to the heart of 'art of coding', that is finding the right balance between:

    saving time and money now (hard coding)

    vs

    saving time and money later (soft coding)




    That comparion is the root of the problem. Soft coding will not automatically save you time and money later, though it will cost you time and money now.

  • Fubar 2007-04-11 01:02
    What fun! I know of a similar system: it 'implemented' an object system by simply defining four tables in a relational db: ObjectType, FieldType, Object, Field (including a column in the ObjectType table that indicated relationship (association/containment), and a column in the FieldType table that indicated whether the field was an array or not). The small problem of making the whole thing look like an object system was left as an exercise for the application programmers. Every tier (web, model) of the application ended up creating its own 'wrapper' army to make the darn thing work.
  • highplainsdrifter 2007-04-11 01:42
    I work at a similar company where everything is "configurable". Some of our programs have a whole directory or two of configuration files in various formats. When asked why our configurations are so complicated the standard answer is "flexibility - we never know what our customers might need." Nonetheless, in the face of such awesome complexity, er, I mean flexibility, we still seem to have to develop new code and new configuration items for every customer. Go figure.
  • jdj 2007-04-11 03:01

    private void attachSupplementalDocuments()
    {
    if (stateCode == "AZ" || stateCode == "TX") { // BUG!
    //SR008-04X/I are always required in these states
    attachDocument("SR008-04X");
    attachDocument("SR008-04XI");
    }

    if (ledgerAmnt >= 500000) {
    //Ledger of 500K or more requires AUTHLDG-1A
    attachDocument("AUTHLDG-1A");
    }

    if (coInsuredCount >= 5 && orgStatusCode != "CORP") { // BUG!
    //Non-CORP orgs with 5 or more co-ins require AUTHCNS-1A
    attachDocument("AUTHCNS-1A");
    }
    }

    This is Java code, isn't it?

    This will not work. In Java you should never use '==' and '!=' for String comparisons; you need to use '.equals(...)'.

    Yes, that's a Java WTF.
  • Grrr 2007-04-11 03:09
    {app.cfg}
    #used in docMgmt.java:attachSupplementalDocuments()
    LEDGER_AMOUNT_REQUIRING_AUTHLDG1A=500000

    ====

    As some people wrote before, making a useless name for constant doesn't show the introduction of constant is wrong.

    Now, if that app.cfg had something like:
    # amount of money,
    # after which extra forms required:
    LEDGER_THRESHOLD_AMOUNT=500000

    I would maintain that it is way better than using direct values in code.
  • Bryan 2007-04-11 03:16
    This article seems pointless to me. Of course hard coding is better sometimes, and soft coding other times! You said nothing about the interesting part, which is how to choose one approach or the other.

    In your example: Is this a quick script for your own use, or an application being broadly distributed? Is it run on a server or on many clients? Is it in a compiled language? How often do these business rules change? Does the overall system contain a small or large number of business rules?

    I think experience is how most people learn to strike a balance between hard and soft coding. At my job we are trying to maintain and fix a big web system which was built on a long, redundant process of incremental hard coding. It's such a hideous mess that I want to cry when I have to touch it.

    It's all about balance, folks!
  • BAReFOOt 2007-04-11 03:20
    1) There is no black/white. There is always a gray area. ALWAYS!
    1b) ...and in every dimension/factor. Time, space, coding hardness, WTFiness...
    2) Everything is relative. EVEYTHING!
    2b) ...and in every dimension/factor. Time, space, coding hardness, WTFiness...

    As a result, what counts is only the basic formula with some common, and your personal input factors. (meaning there is NOTHING without a personal/group(s) bias)
    That formula is missing from the original article. So it's useless*.

    And so i finish it, by proposing a formula:

    - How often and where does the rule/setting have to change?
    - Depending on this, choose how hard you will implement it.

    Resulting in:

    hardness = probabilityOfChange * probabilityOfDifferenceBetweenUsers * personalBias

    I'm never actually calculating this with real numbers. It's a thing of experience and gut-feeling. But it works pretty well...

    By the way: The same problem is the conflict between vi (extreme power user) and windows (extreme noob). We could have both. At the same time. In the same software. Changing with the time the user spends using it, multiplicated by his personal bias of how much he wants to get into it. Anyd everybody would be happy.

    (CAPTCHA: WHO THE FUCK CARES??)
    _____
    * Such statements NEVER are meant globally, because there is no *global*.
  • brazzy 2007-04-11 03:35
    eyrieowl:
    i think a lot of other people have raised most of the salient points about why soft-coding makes sense for certain tasks. but i couldn't not say this: a poor implementation of an idea is no reason whatsoever to dismiss the idea. it seems to me that a lot of alex's argument rests on his (i'm sure well-founded) dislike for the rules engine he was exposed to. but just because someone was able to do it badly doesn't inherently mean it shouldn't be done.


    No. The point is that if you really do a good implementation and follow through to the logical conclusion, you end up where you started: you're writing your logic in a fully-fledged programming language, changes need to be tested and you probably have a non-trivial deployment process.

    So you have won nothing over just writing the rules in code in the first place, you have only wasted a lot of time and effort. And if you DON'T do it well, you end up with a hideous monstrosity of a language. Designing and implementing programming languages isn't really something most coders have a lot of experience in.
  • LKM 2007-04-11 03:38
    You're writing business logic in code? Use a system where you can model that stuff.
  • brazzy 2007-04-11 03:48
    chrismcb:

    Lets suppose, instead of just having two states with odd forms, you have 50 states. What would you rather maintain a table, or a bunch of if statements?

    I'll take the if statement, because it's not going to be one simple table as soon as the rules don't all follow exactly the same pattern. That was the point: the example code seems simple enough to make "configurable". But it won't stay that simple.
    What is easier to deploy, a new set of dlls or a new database file?

    What is easier to test a new dll or a new database file?

    What is easier for the customer? Update thier data, or wait for the vendor to release the new version

    Your deployment process must really suck if you see a big difference here.
    An now what happens when you need to run something for year 2006 vs 2007? You can take old buggy version of the app built in 2006, and live with the bugs. Or you can take the newer cleaner less buggy 2007 version and plug in the 2006 data.

    Decouple your data as much as possible. Sure it isn't always possible, or prudent. Sometimes it is easier for everyone to bake stuff into the app (again thats our job). I just think that the example given is a PRIME example of something that shouldn't be in the code, despite the article claiming otherwise.

    And I think that you're not getting it: there is no data here, there is logic. And it will keep the properties of logic (like the possibility for bugs and inconsistencies) even if you put into a database. You'll only have added complexity and more potential for bugs by separating some of your program logic from the rest and transferring it into a format not really meant for expressing logic.

    You talk about running the "less buggy" 2007 software with the 2006 "data". But what if it's really the 2006 "data" that was buggy? Or if the "data" format changed along with the code to accomodate different patterns of logic? Or if the 2006 "data" contained workarounds for bugs in the 2006 code?
  • vermeil 2007-04-11 03:53
    Good article!

    Of course, there is a middle ground between hard and soft code as described here. In languages (such as Lisp) where code is data, a function like this one can have a sequence of condition--documentID pairs passed to it.
  • DevZee 2007-04-11 04:47
    Hmmm... all in this sample is based on hardcoding some values in a single method, but who has ever implemented a solution where some business rules only appears at one place - in the whole app.? Also, I must say, I'm no big fan of over-generalization or "obscurity by flexibility", but to hardcode string values and magic numbers is just mean.

    The better solution is to centralize common rules etc. and reference such with constants or wrapper methods (e.g. if (SomeValueIsOverLimit(someValue))... or if (SomeDateIsOverDue(someDate))... etc.)
  • Asd 2007-04-11 05:01
    Great article. Of course hard coding is bad if taken too far, but "soft coding" (great term) is very dangerous and a great temptation to developers with a couple of years experience who think that they are serious programmers now. I've seen some horrible XML "configuration" controlling applications. My rule of thumb is: if you put a conditional in your config then you are definitely soft coding.

    Most enterprise software is written in Java. Java has interfaces, reflection, and jar files, so it is almost as easy as it would be for a scripting language to keep your changing business logic in a separate jar that you can build separately and drop in when needed. Moving the logic to XML is just a way to skip QA.
  • vr602 2007-04-11 05:03
    Of course the neat way of implementing rules in your database ( assuming your dbms allows it ) is with dynamic SQL: If you put in your 'rules' table something like set_command = "fl_excess_flag=1" and
    where_clause = "am_invoice>20000"
    then it's easy to get that to generate the SQL statement "update blah set fl_excess_flag=1 where am_invoice>20000". Easy to maintain, easy to understand, nice and flexible/extendible. Purists will hate it, but it works a treat.
  • anm 2007-04-11 05:20
    Once I read an interesting book by some game developper, who described the effect described in this article. For game developpers working together with game designers (no developpers) it is exactly the same problem.

    They define an easy scripting language, but are (sooner or later) confronted with numerous feature requests by the designers. The author wrote something like this:
    "If you get to the point where the scripting language is more complex than the underlying programming language, you know that you failed."

    So for me this article was nothing new (also from practical perspective, -sigh-) and for the gaming industry the problems are exactly the same.
  • me 2007-04-11 05:21
    That's why they invented dynamic compilation. This would be trivial to implement as a set of code snippets in a 'database', each code snippet could perform any test on the data. This seperates the 'hard/soft'-coded business logic from the functionality of the application.
  • Mr Magoo 2007-04-11 05:24
    joe_bruin:
    Justin Buist:
    Ebs2002:
    #DEFINE NUM_DAYS_IN_WEEK 7

    If you're counting from 0 it could be 6.


    No, there are always seven days in a week.


    OMG!! you just hardcoded a number in your comment!!
    A real coder with enterprise experience (TM) would do this instead:

    #define NUM_DAYS_IN_WEEK 7
    No, there are always NUM_DAYS_IN_WEEK days in a week.


    actually, a real coder would not use the pre-processor. All configurations should go into a XML file on a remote site.
  • dkf 2007-04-11 05:27
    Bell Endian:
    1 is 1 and 10 is 10 in big endian notation.
    It is in little-endian notation too, but it helps if you stand on your head or move to Australia.
  • PC Paul 2007-04-11 05:36
    ifthenelse:
    Uh, what you should have been using is an iterator and avoided the problem altogether.

    In pseudo-code cause I don't have all the information:

    something_type::iterator itr = something.begin();
    
    for (; itr != something.end(); itr++)

    Or "++itr" if you prefer, I hate that syntax. Yes I know the risks.


    You hate a syntax ? You need to get out more.

    AFAIK there aren't any risks to using itr++ instead of ++itr standalone like this, but itr++ will often be slower.

    What will be nice will be doing it in C++ 0x...

    for (auto itr = something.begin(); itr != something.end(); ++itr)
  • canatella 2007-04-11 06:21
    Saladin:
    #DEFINE NUM_DAYS_IN_WEEK 7
    #DEFINE ONE_MILLION 1000000
    #DEFINE NUM_SECONDS_IN_MINUTE 60


    #DEFINE TRUE false
    #DEFINE FALSE true

    #DEFINE MAYBE -1
  • Sunstorm 2007-04-11 06:25
    Business rule values are always inevitably bound to their behavior. Configuration options don't do here. Best thing maintainability-wise is probably to separate the entire set of business rules into it's own set of files, values and code included. Maybe one can call it some sort of layer... A tier, even. I'm a genius.
  • Brendan Dowling 2007-04-11 06:29
    This is the best article yet. Seriously. A set of resources that define the runtime behavior of the program is basically another set of code, only one that is written in a weird application-specific language. Deploying an EXE is exactly the same amount of work as deploying a new set of data files. Generally you're going to distribute them together because otherwise the number of combinations will explode (imagine v1.0 exe with v1.2 data). Testing the application is the same amount of work whether or not the code exists in the EXE or in data files. Debugging is harder because there is code that comes from configuration files and chances are you didn't build a debugger for your homegrown data language. As others have said, using a dynamic language like Perl, Ruby, Tcl, Lisp, Scheme, can allow you to easily have runtime loadable code if you think you might want it. But implementing functions that execute data based on rules is a huge waste of time.
  • Eanna Butler 2007-04-11 06:30
    A set of "config files" can also be used to generate code. The code then doesn't interpret the config files at runtime, rather source files are generated from the "config files", compiled, and deployed. I like that idea. Works for lots of things, but obviously not everything! Makes repetitive tasks easy, makes for standardised source code adhering to a predicatable style and pattern, can make debugging of the generated source simpler, can make for highly-performing code, or rather code that doesn't run like a dog, and often makes for simpler deployment processes.
    An obvious shortcoming of generated code is the maintenance of:
    - generated code (generation is rarely round-trip - i.e. to edit generated source rarely will alter the config that generated the source. If Debugging is (a) finding bugs, and (b) fixing bugs, then code generation will make finding bugs easier, but fixing the bug harder)
    - the generator(s) (often means lots of effort, or effort by a team of well-established developers)
    While the author proposes that Soft Coding doesn't suit Business Rules at all, the use of configuration outside of source when it may be a customer requirement is then .. a requirement. This typically holds when
    - the software is a product that is delivered to multiple customers, rather than being a bespoke development
    - the software release cycles are long
    - the target industry is fast-moving
    Fundamentalism, and hard-and-fast rules, are both designed to sate the uninterested, the thoughtless, the inexperienced, and the unintelligent. Much of the articles on the web about programming take the fundamentalist route, which demands criticism that extends beyond the content and into the philosophy that drives the content.
    I like the author's viewpoint, that programming languages are business-rule containers. However, I find the idealism presented within misleading to those who aren't practised.
    In an ideal world, one single approach would work for everything. We do not exist either in an ideal world, or in a world of idealism, and while we attempt to control the microcosm of our software world, idealism unfortunately does not work in this context.
  • JM 2007-04-11 06:51
    Funny you bring this one up. I had this *exact* example on a project (COBOL based) about 20 years ago where the requirement was to process payruns on Tuesdays until the end of time.

    The developers refused to do this even though it was a *legal* requirement because they'd have to "hard code" all future dates which were Tuesdays into their module (there was only one affected), and the Team Lead came over to gently put me right about modern development techniques.

    After I pointed out the mod-7 trick above, he went off perfectly happy - "chuffed" actually, because it was a neat trick he hadn't seen before.

    They still hard-coded the '7' and the '2' (the week begins on Sunday) though.
  • Jones 2007-04-11 07:19
    Very, very good article indeed. I used to be responsible for maintaining and debugging a platform that could have been simply implemented with Java, but no, of course it also included all kinds of differently formatted config files, XML files and also some configs in database. It really made me think about the correct level of abstraction. And yes, it is not an easy puzzle to solve!
  • bRain Man 2007-04-11 07:48
    Therac-25:
    Oh yeah, this was covered 26 years ago:

    The only way to implement an extensible system using an unsuitable language, is to write an interpreter for a suitable language and then use that one. -- rms, 1981


    That's neatly rephrased in Greenspun's Tenth Rule:
    Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

    And of course, due to Zawinski's Law, it will also read your mail.

    I think I might like to try a different approach for my next application. Start with an MUA written in Common Lisp and hack it until it also does whatever else I need.

    -L
  • tastey 2007-04-11 07:58
    Ebs2002:
    I always cringe when OTHERS cringe
    #DEFINE NUM_DAYS_IN_WEEK 7


    This has nothing to do with the value changing, but about readability.

    Ebs2002:
    #DEFINE ONE_MILLION 1000000


    Agreed, silly.

    Ebs2002:
    #DEFINE NUM_SECONDS_IN_MINUTE 60


    This has nothing to do with the value changing, but about readability.
  • bcammack 2007-04-11 08:24
    I think it's safe to say that the lesson is to know why you are coding what you are coding the way you are coding it and have captured all of the necessary information to make an itelligent decision on how to do so.
  • CrazyOnYou 2007-04-11 08:28
    I had an intro programming professor who preached what he called "the rule of three":

    If you use a value more than three times across your module(s), it should become a named constant; if you use a section of code three or more times, it should become a function. That seemed to strike a balance against overly generalizing into "soft coding" while realizing some of the performance benefits of "hard coding".
  • Not Dorothy 2007-04-11 08:41
    Chris:
    The equation for the area of a circle is not subject to change. So that would be like a business rule that would be hard coded. Maybe which documents to attach or whatnot are not business rules but business variables. Worse are config files that aren't documented and then it's like the whole freaking app is one gigantic linear doomafalache.


    If I remember there were some Christian fuckwits in Kansas (it's always Kansas) that wanted pi to be 3 because of something in the bible, so no you couldn't hardcode this, in fact you couldn't use the constant PI in your calculation.
  • Asd 2007-04-11 08:42
    Most readers seem to be missing the point: this is not about defined or inline constants, it is about configuration/overly data driven apps.
  • foobish 2007-04-11 09:06
    I just can't get myself to agree with this article.
  • B. K. Oxley (binkley) 2007-04-11 09:11
    A beautifully written article.
  • sionide21 2007-04-11 09:40
    Justin Buist:
    Ebs2002:
    #DEFINE NUM_DAYS_IN_WEEK 7

    If you're counting from 0 it could be 6.

    No it would still be 7. 0 to 6 still spans seven numbers.
  • KenW 2007-04-11 10:04
    gerrr:
    Some people do take their anti-hard-coding bent too far.

    /snip
    Things that are only being used within a small scope, or only used once, usually do not need to be constants.


    I wish you were the one I inherited code from instead of the person I really did. :-)

    The (Delphi) code is full of things like:

    const
    bUsePrinter = True;
    bUseScreen = False;

    procedure DoReport(Data: Whatever; Destination: boolean);

    And in the calling code:

    Res := MessageBox('Click OK to print, or Cancel to preview', mtConfirmation, [mbYes, mbNo], 0);
    if Res = mbYes then
    DoReport(intData, bUsePrinter)
    else
    DoReport(intData, bNoPrinter);

    I really, really hate it! :-)

    (And yes, the other WTF-worthy stuff is really there too.)
  • Therac-25 2007-04-11 10:12
    sionide21:
    Justin Buist:
    Ebs2002:
    #DEFINE NUM_DAYS_IN_WEEK 7

    If you're counting from 0 it could be 6.

    No it would still be 7. 0 to 6 still spans seven numbers.


    This whole conversation deserves to be a WTF of it's own.



  • Glazius 2007-04-11 10:28
    Hmm.

    This looks like a job for an IDocumentAttachmentStrategy.

    Or has GOF stuff become WTF now?

    --GF
  • JTK 2007-04-11 10:57
    Not Dorothy:
    Chris:
    The equation for the area of a circle is not subject to change. So that would be like a business rule that would be hard coded. Maybe which documents to attach or whatnot are not business rules but business variables. Worse are config files that aren't documented and then it's like the whole freaking app is one gigantic linear doomafalache.


    If I remember there were some Christian fuckwits in Kansas (it's always Kansas) that wanted pi to be 3 because of something in the bible, so no you couldn't hardcode this, in fact you couldn't use the constant PI in your calculation.


    Actually, it was Indiana, and it had to do with bad and lazy mathematicians, not Christians, no matter what your opinion of them.

    See http://www.straightdope.com/classics/a3_341.html
  • TheJasper 2007-04-11 10:57
    brazzy:

    Designing and implementing programming languages isn't really something most coders have a lot of experience in.


    which is a shame, because what do you think you are doing when you do any (non-trivial) programming? People have mentioned Greenspun's Tenth Rule, which I actually have never heard of. What I have heard of is the saying 'Ask a computer scientist to solve a problem, and he will come back with a language perfectly designed for solving your problem in'. Ok its probably an old maxim, which probably felt more true back when you had to have a high level degree to even look at a computer. However both sayings are really trying to say the same thing. This is not meant as a bad thing either.

    However, I can't really back the main article. Many people have allready pointed out the problems in coding. Really there is never an excuse to not put that hardcoded value into a constant defined at the top of your file. However, the article does seem to imply that it has more to do with configuration files. Yes, there is such a thing as having to many config files spread over to many places. In fact, you're config file will probably be defined in a config file if you're not carefull. This tells you that you probably have a bad design. probably.

    However, there is almost never an excuse for hardcoding. Certainly not 'my app won't be used more than once' (or any small number). How many legacy apps/scripts exist that were only meant to be used once?

    What it all comes down to is good design. Seperate your business logic from your presentation, etc., etc.. Avoid use of modern design and patterns simply to be using modern designs and patterns. Not everything needs to be in a config file, but unless its 0, put constants where they belong. It improves readability and maintainability. Yes, even if you use them only once, because maybe you only thought that when you started. No to mention that if you have to change the value of Pi, it's easier to do it in a defined consant the searching your file for it. Maybe not much easier, but still.

    Oh, and all rules have exceptions. except this one ;}

    Just one more thing. If your system, designed to make life easier, requires an expert to use it, maybe it's because the subject matter is difficult enough to warrant an expert. Otherwise you did something wrong.
  • JTK 2007-04-11 11:01
    I remember a class with Marshall Kline (of the C++ FAQ) who recommended a serious soft-coding approach for certain types of problems. But, he also offered this line of wisdom: Look at how the Good Lord designed your arm. It only has three well-engineered joints, which still offer an almost complete range of flexibility and movement. If you were missing an elbow, say, then your arm would be almost useless. But, if you added a couple more joints, then you wouldn' have an arm -- you would have a noodle.

    Only add flexibility exactly where you need it.
  • poochner 2007-04-11 11:08
    Hardy:
    qbolec:
    I've once worked for a company, where the Q&A complained about the use of 'magical constant' 0 in the for loop:


    As if your QA dept actually looks at code!?


    Some QA departments actually take their task seriously and try to Assure the Quality of the product. That includes doing both black- and white-box testing and their own code reviews. Not very damn common, but it does happen.
  • brey 2007-04-11 12:00
    What these people fail to realize is that they just moved the code into the database, so they were writing a compiler to execute the code in this database. I've seen this before and it failed miserably (except for my company which was billing by the hour to create this monstrosity). What a mess!
  • Corporate Cog 2007-04-11 12:31
    Holy moly, let the worms proceed forth from the can. My code base used to have the exact same lines (obj.stateCode == "TX").
    I centralized all the instances of states into one unit and added a function so that the calls changed to stateOf(TEXAS).

    I suppose that's too soft...
  • Loren Pechtel 2007-04-11 12:50
    Count me in the group that favors constants.

    The ONE_MILLION one is garbage--no constant should be named like that, one million isn't meaningful. Rather, it should be named what it's for.

    Yes, you can do the same thing with comments. Think the comments will be up to date, though? My philosophy is that in almost all cases the only thing to comment should be algorithms or externals. If you need any other sort of comment the code isn't clear enough. Note that this occasionally means moving code into a procedure just to put a name on it but so what?
  • eyrieowl 2007-04-11 13:18
    brazzy:

    No. The point is that if you really do a good implementation and follow through to the logical conclusion, you end up where you started: you're writing your logic in a fully-fledged programming language, changes need to be tested and you probably have a non-trivial deployment process.


    That's an unsupported assertion, one that I think is provably false. If you follow *your* logic to it's "logical conclusion", there is no point to any language other than machine language. After all, they're all just languages sitting on top of that. Clearly, though, higher levels of abstraction *do* have value and even you likely don't code machine code by hand. The point to any language that sits on top of a lower level of abstraction should be to provide useful abstractions that make doing common tasks easier. That's the fundamental reason why programming languages exist. It is definitely not the case that every problem requires a full-fledged programming language to solve. My example of computing an IRS 1040 is a perfect case in point. Externalizing the logic of the 1040 to a document that is read by a processor in _no_ _way_ requires a full programming language. The set of operations required is much more limited and specialized. So making an assertion that externaling logic leads inevitably to full-fledged-language-horror is just wrongheaded.

    brazzy:

    And if you DON'T do it well, you end up with a hideous monstrosity of a language. Designing and implementing programming languages isn't really something most coders have a lot of experience in.


    Which entirely misses the point I made -- just because something can or has been done badly doesn't mean it shouldn't be done. You or someone you know might not be the best person to solve a particular problem, but that doesn't mean no one is qualified and should attempt the task. Most coders *I've* met are terrible system architects, but that doesn't mean there aren't *good* architects that you should have designing your system. Likewise, externalizing logic requires a certain skill and has an art to it--if you lack that art, don't assume everyone else does and that the approach is therefore flawed.
  • Greg 2007-04-11 13:21
    You're thinking inside the box. There is a middle ground between a general purpose language (i.e. hard-coding) and throwing stuff in config files (i.e. soft-coding). That middle ground is a domain-specific language (DSL) which is used to generate code. You make it easy to write the business rules in a reasonably straightforward and natural way and make generating the code (and compiling it) part of the build system. As long as you don't try to make your DSL too big or your generator too smart, you're in good shape. It's still code, but it's code in a higher level language.
  • Elsp 2007-04-11 13:37
    http://en.wikipedia.org/wiki/French_Republican_Calendar#Ten_days_of_the_week
    http://en.wikipedia.org/wiki/Discordian_calendar

    Perhaps you should rephrase that:

    "There are always seven days a week when I choose which calendar to use"
  • akatherder 2007-04-11 13:45
    I use "soft coding" to create a framework for simple web forms. Let's say you are writing survey software and you have three clients. Each client will want different questions. So you have to create "components" for them to administer. You give them the textbox, radio, checkbox, textarea, dropdown, etc. components and they can all add/remove their own questions from their own surveys. This can all be database driven to store the type of component, some unique name, and possible answers.

    I would think most web programmers have done something like this or toyed with the idea. It's quite useful and not very complicated. You aren't rewriting a programming language. Instead of editing the code, typing a new question, creating a new <select> box, and adding a column to the database you can just have an admin page to update the database.

  • Corporate Cog 2007-04-11 16:09
    kanna:
    Put a 60 in the code and comment it.


    Come on, who can seriously deny that the code itself should act as the comments as much as possible?

    Strange that such a comment would be posted.
  • James Taylor 2007-04-11 16:30
    Wow - where to start. An article that asserts that because something can be done in a stupid way it must be a stupid thing! If it was really easy to just change the code when the business rules changed, no IT department would have a maintenance backlog (and, in case Alex hasn't noticed, most do). Ask not if you can code it but if you should!
    Longer reponses on my ebizQ blog.
    JT
    www.edmblog.com
  • lackluster 2007-04-11 16:36
    I'm a little surprised no one has brought up the Model-View-Controller methodology and the multitude of frameworks that use XML config files to establish that methodology. Personally I'm all for the separation of business logic, and have reaped the benefits numerous times when redeploying existing applications for businesses sharing few similarities. They typically merge both hard-coding and soft-coding techniques together quite nicely. For instance rather than defining DAYS_IN_WEEK, you would call a function to return that number for you, and the function that was called would be defined in the configuration file. This is handled quite nicely through event-based implicit invocation, a hallmark of several MVC-based frameworks.

    An Introduction to Software Architecture
  • Rexxar 2007-04-11 17:32
    At work, we use a time tracking software in which a day has eight hours and a week has five days. In the previous version it was "one day = 24 hours" and "one week = 7 days" and it was unusable.

  • Zygo 2007-04-11 18:03
    tster:


    Boolean Check_AZ_TX(string stateCode)
    {
    if (stateCode == "AZ" || stateCode == "TX") return true;
    else return false;
    }


    First off, this isn't object orientation and it has nothing to do with it. Secondly, I can only hope and pray that you aren't serious.

    1. If you are going down this road you have set yourself up for MASSIVE code duplication. If you don't want code duplication you can do the following:

    boolean check_TX_AZ(String state)
    {
    return(check_TX(state) || check_AZ(state));
    }

    otherwise you can end up having duplicated code literally hundreds of times.


    That's silly. You don't want to know about which state you're in at all. You want to know which states have some requirement that requires different business logic. So name the function after that requirement:


    boolean state_has_Smarmy_Bletcher_law(String state)
    {
    return state == "TX" || state == "AZ";
    }


    If a new state implements this law, you change the above method. If the forms required change, you implement change the below method:


    String[] forms_for_Smarmy_Bletcher_law()
    {
    return [ "SBL-2003-1", "SBL-2003-2" ];
    }


    and most likely you'll immediately want to write:


    void attach_Smarmy_Bletcher_forms(Document d, Context c)
    {
    if (state_has_Smarmy_Bletcher_law(c.getState())) {
    d.attach(forms_for_Smarmy_Bletcher_law());
    }
    }


  • Zygo 2007-04-11 18:16
    JM:
    Funny you bring this one up. I had this *exact* example on a project (COBOL based) about 20 years ago where the requirement was to process payruns on Tuesdays until the end of time.

    The developers refused to do this even though it was a *legal* requirement


    Who or what, by an act of *legislature*, must be paid on Tuesdays?
  • Zygo 2007-04-11 18:18
    CrazyOnYou:
    I had an intro programming professor who preached what he called "the rule of three":

    If you use a value more than three times across your module(s), it should become a named constant; if you use a section of code three or more times, it should become a function. That seemed to strike a balance against overly generalizing into "soft coding" while realizing some of the performance benefits of "hard coding".


    #define three 2
    #include "parent"

    There, I agree now.
  • Jefffurry 2007-04-11 18:30
    I've worked in more than one industry in which code changes require a great deal of regulatory approval, but configuration changes don't. Part of the "Hard Coding" versus "Soft Coding" evaluation involves the consideration of those kind of constraints (or the lack thereof). So the "best" answer for the same functionality in different industries may be different, even if the language is the same.

  • Dirge 2007-04-11 18:47
    This article really made me lose a lot of respect for Alex, and question the quality of the other writing on the site (which I've been reading for quite some time).

    I'm sure it's often possible to get away with the sort of hackish, fast-but-crappy coding he promotes when it's internal to a company. It's still terrible.

    End users of a program should **never** have to change the source code and recompile just because data (like which states require a particular form) has changed. Source code gets lost. If you buy a product, you probably don't even *have* the source code.

    Oh, wait, maybe the end users should agree to disassemble and hex edit the program because that would save the developers from actually having to *do their job and develop the program properly*.

    What a bunch of lazy, poor developers in this thread. If you want to be a crappy hack that writes unmaintainable code, at least have the decency to acknowledge it and use a scripting language instead so that people can clean up your mess when (not if) it becomes a problem.
  • silverpie 2007-04-11 18:58
    tster:
    wrong, There are 7 days in a week if you are using a calendar that specifies that there are 7 days in a week. Indeed, calendars besides Gregorian calendar exist.


    And all of the ones still in use (I refuse to count the Discordian) have either no week at all or a 7-day week. The last one to survive more than a year that used any other week was the French Revolutionary.
  • Marginal 2007-04-11 19:07
    Elsp:
    http://en.wikipedia.org/wiki/French_Republican_Calendar#Ten_days_of_the_week
    http://en.wikipedia.org/wiki/Discordian_calendar

    Perhaps you should rephrase that:

    "There are always seven days a week when I choose which calendar to use"
    Fine. When you find an organisation that does business on either of those calendars you can come after me with a big pointy stick. Until then I'll continue to assume that there are 7 days in a week.
  • Marginal 2007-04-11 19:31
    Dirge:
    End users of a program should **never** have to change the source code and recompile just because data (like which states require a particular form) has changed. Source code gets lost. If you buy a product, you probably don't even *have* the source code.
    Straw man. No-one is suggesting that the customer recompile.

    brazzy:
    chrismcb:
    What is easier to deploy, a new set of dlls or a new database file?

    What is easier to test a new dll or a new database file?

    What is easier for the customer? Update thier data, or wait for the vendor to release the new version
    Your deployment process must really suck if you see a big difference here.
    This is the key point. Move some logic out of "code" and in to a "data" file (or domain-specific scripting language) if you like - but when you come to change that logic you're still changing the behaviour of the program. So you need to test the change with the same degree of thoroughness irrespective of whether the change is encoded in code or in data.

    The difference is that when the logic is encoded in a data file you are implicitly encouraging your customer to change that data file - so multiplying your testing by n.
  • barf coding 2007-04-11 19:40
    I always felt that code should be something that looks nice, and not only to you, but to another developer. Not only that, it should do what it was meant to without kludge. There should be no excessive use of complex coding concepts when they are not needed. A lot of people want to flex their programming muscles, and therefore misuse code all over the place in order to feel superior and show off their elite knowledge. Soft coding is a wonderful example of that, but I can't say that I am exempt from misuse... It's a constant process trying to find a happy medium, or a constant process to understand the tools you have been dealt. With new development abilities on the rise (such as LINQ) people are bound to abuse and misuse, and to further progress ways of doing things efficiently and eloquently as well. I have a feeling we all generally end up on both ends of the stick!

    In the end though, if I can't clearly communicate to another developer what my code is supposed to do, then I might of failed in the process of what I was trying to accomplish. I want to write something, that when read by another, they can relate.

    And then the process of passing the torch becomes less painful. Frameworks, patterns, and the such help to eliminate it a little, I guess. But in the end, I think we want something that most eloquently states what we were trying to accomplish, and sometimes too much hardcoding can turn a good idea that might of made a good short story into a burdensome repetitive novel. Happy balance, hard to find.
  • barf coding 2007-04-11 19:42
    oh, and business requirements. A lot boils down to business requirements.
  • Stevenovitch 2007-04-11 22:20
    Uh huh, if anything this post and it's comments prove that a lot of you need to be a bit more open minded, as half of you vigorously claim to have the one true answer and manage to be more righteous than the other half with the other one true answer.

    Confucious says: be liberal in the input you accept and conservative in the output you emit.

    Also, if you really have a way to know the "one true answer" for every situation regardless of exterior considerations then please write me a book, as I'm tired of weighing the endless number of contextual factors that go into producing this code crap.
  • Mandor 2007-04-11 22:36
    As someone who both admins and codes, I find this article horrifying. It sounds like it was written by someone who has the luxury of writing code and not actually maintaining systems and code over the long term.

    First off, making everything configurable should be really "cheap." Most languages have some sort of framework for making things easily configurable. Even if your language doesn't have such, you will have to develop one for the cases that are inarguably hardcoding. Once you have an infrastructure for easy configuration, it should be really cheap to make everything configurable.

    Secondly, from a full lifecycle perspective, often the things that change are not the things that you anticipated upfront. The more things that are configurable, the easier it is to make changes during the lifecycle of the program. Sure, some changes will require a recompile, but by putting as much as is reasonable in a configuration file, you minimize this.

    Also, as others have observed, in many environments, it's a lot easier to get permission to change a configuration than to change code. Code changes require careful testing, since coders tend to break things; config changes also require testing, but can be more easily backed out.

    And also, "recompiling" is not always a simple matter. After N years, the compilers, tools, and platforms might themselves have changed, such that even recompiling original source might not produce new binaries that behave identically to the original binaries.

  • Beltira 2007-04-12 00:09
    NUM_DAYS_IN_WEEK, ONE_MILLION, and NUM_SECONDS_IN_MINUTE will yield better results when grep'ed on as well as the first reply points out that it avoids typos and adds clarity to hard values.
  • Watson 2007-04-12 01:23
    Therac-25:
    These discussions about date constants are rather odd -- does anyone still do date math themselves? Aren't there solid date and time libraries in every language? I haven't used anything except Date::Manip in Perl and the forest of inheritance trees of objects in Java to do this stuff since I was bitten the first time (there are at least two days in the year (in my locale) that aren't 86400 seconds long....)


    Date/time arithmetic is merely the canonical example; the problem domain is widely recognised; there's the potential for lots of magic numbers (like 60, and 146097) that are either not obvious, or ambiguous; and calculations that it's easy to botch. Which is why there are libraries. Written by alien civilisations far superior to ours. Thank goodness we humans never have to write libraries.
  • Anonymous 2007-04-12 01:44
    gerrr:
    Some people do take their anti-hard-coding bent too far.

    I have worked on programs where everything that would be a string literal or number in a formula is turned into a constant. It makes it ridiculously difficult to figure out what is going on because you have to constantly search and hunt for where the constants are defined. (because there are several hundred)

    You don't use 'ctags' or 'etags'?
  • Rhialto 2007-04-12 04:45
    cparker:

    One billion could equal either of the following:

    1 000 000 000
    1 000 000 000 000

    Conversely, 1 000 000 000 could be read as "one billion", "one thousand million", "one megamillion", or "one milliard".
    Yes, for instance in Dutch,

    1E06 = miljoen
    1E09 = miljard
    1E12 = biljoen
    1E15 = biljard
    1E18 = triljoen
    1E21 = triljard
    etc

    although such large numbers are not usually pronounced :-)
  • pb 2007-04-12 08:45
    It doesn't matter where you start counting. Even if you start from 42, the number of days in a week will still be 7.
  • speaking of wtf's 2007-04-12 08:49
    ok thats enough. To imagine that users of software cannot "change business rules" is just indicative of how out of touch Alex is with real use of real software. Alex is truly his own web page, "worse than failure."
    <p>
    Moron. And your forum software sucks.

  • RON 2007-04-12 11:30
    This article was clearly written by someone who has never worked in the software industry for any major client.


    Yes, executables are easily recompilable. Yes it's data, and we can send it out.


    But you're forgetting something: security audits. We work with a lot of banks, and the process to approve a single assembly for usage can take over a month, sometimes up to 3 or 4 months. They go over everything with a fine tooth comb, hire security auditors and private firms, etc.

    Rolling out a new version of a .DLL is a painful and long process in the banking industry.


    And of course, the banks can't afford any downtime either. A rollout of a new assembly needs to take the system down, which is a long and arduous process that needs to be coordinated between thousands of people. It's simply not realistic in any way to expect the company to shut down operations and spend thousands reauditing a DLL simply because they want THIS document to apply to NY state, rather than THAT one.


    A database patch, however, takes one person 10 minutes to apply. Millions of dollars are saved, and life goes on.


    Just because soft-code is harder to write, don't assume it's a bad solution.
  • na 2007-04-12 11:50
    Wow, I've lost all respect for this site, now. This article basically says, let's use lazy, hack-ish coding practices because it's easier for us in the short term.

    For anyone who has ever worked with a sizable user base, and/or any kind of change control policy, "just recompile and re-release" is not a trivial thing. I would much rather update a row of data (a dollar amount threshold, for example, from 20,000 to 30,000) than to have to make a code change, get approval form 3 managers and a vp, go to a change control meeting, and then move the change through test, qa, then to prod.

    Yes, some of you will say that the release process is the
    problem here, but banks are kind of funny about what gets released into their production environment (and rightfully so).

    Anyways, in my opinion, this article just advocates horrible coding practices.
  • j. 2007-04-12 12:27
    for a second I that you were meaning What The F...
  • Matthew Wakeling 2007-04-12 13:08
    What does this article say about that well-known mail transfer agent, sendmail? Perhaps the most soft-coded application I can think of.
  • bd 2007-04-12 13:25
    na:
    I would much rather update a row of data (a dollar amount threshold, for example, from 20,000 to 30,000) than to have to make a code change, get approval form 3 managers and a vp, go to a change control meeting, and then move the change through test, qa, then to prod.
    Your release management is sloppy. You should have the same procedure in both cases.

    Not to mention that giving developers DB access (probably unrestricted one) is another disaster waiting to happen.

    Kinda reminds me of net admins that shut down all ports but port 80 "to improve security". And then notice a month later that there are more SOCKS proxies than HTTP servers running on port 80.
  • na 2007-04-12 14:18
    you're reading that much too literally. Obviously, a dba would update a data row.

    And my point isn't a debate on release management, it's that the article advocates poor coding practices.
  • bd 2007-04-12 14:41
    na:
    And my point isn't a debate on release management, it's that the article advocates poor coding practices.
    You're not making that point with your original post, though. All you're saying is that it's easier on your project to get a database change approved than an application one. I can think of (at least) three different scenarios for that.
  • na 2007-04-12 15:22
    No, I'm saying that it's easier to change a business rule when it is data driven than when it is in the source code.
  • Gentian 2007-04-12 15:49
    For me there's a danger that this whole soft coding article is WTF Jumping the Shark.

    The whole name change seemed worrying, but I was coping.

    But seriously... this is a WTF? The article says that nothing in the first example is hard coded. Huh? It's ALL hard coded! It may be right to be hard coded but it is hard coded.

    I have often found myself guilty of over generalising, and yes it can compromise simplicity and execution speed, and yes, even development time. So there is a point to be made.

    But, like I said, this is a WTF?

    Thanks to everyone who jumped in to argue against Alex's point. And yes, as commenters to those say, it's sometimes appropriate to do it the hard coded way.

    But no way it's a WTF! A WTF is never the right way, not something which very often is and should be the only way.

    Here's why WTF might have jumped the shark. Every time I read an article now I've got to think, is this whole article just completely wrong?

    Sad to say this. But it's on my mind.

    Gentian
  • rblaa 2007-04-12 16:35
    It’s a pretty silly fear to have. The whole point of software (hence, the “soft”) is that it can change that it will change. The only way to insulate your software from business rule changes is to build a completely generic program that’s devoid of all business rules yet can implement any rule. Oh, and they’ve already built that tool. It’s called C++. And Java. And C#. And Basic. And, dare I say, COBOL.


    Yes! Finally.

    As soon as you have configurable rules that affect behaviour, you need to think very very careful about inventing yet another home grown configuration format, which in effect is just another interpreted language.

    The points about dynamic scripts vs compiled only languages are really irrelevant: you have "code rules" that you change to modify behaviour. Why not use an existing notation such as a programming language. It's much easier than inventing your own.

    Either way, you have to properly test the system and re-release. Those who think that only official source code changes need an official QA cycle and that configuration file changes do not are simply releasing potentiall buggy software.

    One valid reason to have a configuration rules file is when users want to change things without rebuilding. Even then, consider using a preexisting scripting language (e.g. lua, scheme) rather than inventing a complex xml format.

    Here's the rule of thumb: as soon as you need rules that are complex enough, you are programming. Programming is best denoted via a programming language.

    Most people are terrible at inventing programming languages. Furthermore, almost all XML "languages" for controlling complex behaviour just plain suck. The only reasonable one I know of is ant, and even that can be tedious.
  • barf indeedy 2007-04-12 18:10
    Can't we all just get along? :D
  • Jo 2007-04-12 18:38
    One billion could equal either of the following:

    1 000 000 000
    1 000 000 000 000

    Having solid definitions of things like this--whether it be in configuration files or #defines--should be a requirement if you're writing a program that is going to be used--and developed--internationally.


    No! In a computer program, the interesting thing is how many zeros you have behind the 1. Things like millions and billions have nothing to do in a program at all. Inside source code it's 1e9 or 1e12. Whether you choose to name something a billion or a milliard is an I/O-issue. This should be handled by localization (if at all).

    Most programs rightly handle this by reading and writing numbers consisting of strings of digits, instead of numbers consisting of strings of letters (e.g. "24" not "twenty four").
  • Peter 2007-04-13 00:59
    Great instructive article please have more of these.
  • c6jones720 2007-04-13 08:39
    I work for a company that deals with embedded computer systems controlling machines. I have seen first hand what happens when you hardcode things into embedded software. You end up with over 300 versions of the same program with nasty little:

    #if
    blah..
    #else

    #define this...
    #if defined that...

    statements all over the place and completely unmaintainable code. No wonder they fired all thier old programmers!

    I am 100% in favour of softcoding.
  • XenonXavior 2007-04-13 14:06
    For all of you who are frightened by this, take it with a grain of salt. For the banking industry, this may not be the best practice. For some piece of proprietary software that may never change for 5 years, it's not a bad policy. I've seen too much generic code that allows for a wide range of possibilities that will most likely never happen. In the event that a value or policy needs to change, changing the source would be marginally more difficult than changing a configuration value in some other place.

    Each choice should be made in its own context. Why plan for an eventual future that may not happen when it's easier to deal with the issues at hand? Don't ask for a pound of prevention over an ounce of cure.
  • Pavlov's Dog 2007-04-13 15:34
    Mr Steve:
    This article really gets to the heart of 'art of coding', that is finding the right balance between:

    saving time and money now (hard coding)

    vs

    saving time and money later (soft coding)


    for whatever weird reason, coders generally think in terms of soft coding and making great frameworks that will change the world! (just look at how many ajax frameworks and javascript form frameworks there are currently out there).

    that's only one side of the art

    people (publicly at least) say they dislike hard coding and hacks. personally i think that they're great. alot of the code that you currently write is for products that have a half life of less then 2 years. often there's no reason to abstract the hell out of your code cos your product will get binned and replaced, so your abstraction is simply a waste of time and energy.

    so it's important to be mindful of this and go for balance.


    To quote Albert Einstein, "Everything should be made as simple as possible, but not simpler."

    Another saw along those lines goes, "every problem is not a nail, and every tool is not a hammer." Sadly, I see too many developers wielding the non-iterative/non-feedback development methodology hammer (aka 'development in a vacuum').

    Choosing to hardcode rapidly changing specifications, is just as bad as wasting time 'softcoding' specifications that haven't changed since Dinosaurs ruled the Earth (1950 or so ;) ).
  • P-Bear 2007-04-13 15:47
    rblaa:
    Either way, you have to properly test the system and re-release. Those who think that only official source code changes need an official QA cycle and that configuration file changes do not are simply releasing potentiall buggy software.


    If your configurations are breaking your application you are obviously not designing your tests to truely exersize the modules properly.

    Test based development forces you to think about the boundaries, and your tests that exersize the code should cover all those bases (e.g. Top/Bottom boundary failures AS WELL AS what is expected - test for failure as well as for success - all tests should pass or you have a gap that needs to be filled).

    You should know that your code is going to fail gracefully regardless of what a user throws at it - and this goes for configurations - perhaps ESPECIALLY for configurations - as well. Failing gracefully is NOT a bug.
  • fly2 2007-04-14 17:01
    [quote]Lets suppose, instead of just having two states with odd forms, you have 50 states. What would you rather maintain a table, or a bunch of if statements? [/qoute]
    Probably the table
    [quote]What is easier to deploy, a new set of dlls or a new database file? [/qoute]
    typically dlls
    [quote]What is easier to test a new dll or a new database file? [/qoute]
    typically dlls
    [quote]What is easier for the customer? Update thier data, or wait for the vendor to release the new version[/qoute]
    Typically waiting
  • RobFreundlich 2007-04-15 10:40
    I agree with the previous comments suggesting balance and moderation. In any problem/spectrum-of-possible-solutions combination, there a sweet spot that is right. The artistry is in finding that sweet spot.

    I'm involved in an evaluation now at work where we're trying to select a web application framework. Should we roll our own, using basic concepts, fairly hard programming methods for things like MVC, layout, components, and AJAX, and just enough glue to bring it all together? Or should we look at the many soft frameworks out there that provide much more complete and flexible solutions?

    No-one on this forum can answer that question, because no-one on this forum knows our particular situation. The same holds true for Alex's original article and YOUR particular situation. YOU know your situation best, and YOU can therefore decide where your sweet spot is.
  • RobFreundlich 2007-04-15 10:48
    na:
    I would much rather update a row of data (a dollar amount threshold, for example, from 20,000 to 30,000) than to have to make a code change, get approval form 3 managers and a vp, go to a change control meeting, and then move the change through test, qa, then to prod.
    ...
    Yes, some of you will say that the release process is the
    problem here, but banks are kind of funny about what gets released into their production environment (and rightfully so).


    I think the point being made by some here (one with which I agree) is that when you go in and change that database row, you ARE releasing something into the production environment. There's no functional difference between the following two actions:

    1. changing a line of code that reads "if foo > 12345" to "if foo > 54321"

    2. changing a sometable.somecolumn from 12345 to 54321, if the code reads "if foo > sometable.somecolumn"

    The net effect is that IN THE PRODUCTION ENVIRONMENT, foo is being compared to a different number. If changing the database doesn't require a full QA cycle, then changing the code doesn't either. The same is true of any statement that changing config somehow requires less testing than changing code.

    If your bank (or whoever) doesn't understand that, then it is your responsibliity to explain it to them, and to try to get them to fix their release process.
  • RobFreundlich 2007-04-15 11:03
    lackluster:
    For instance rather than defining DAYS_IN_WEEK, you would call a function to return that number for you, and the function that was called would be defined in the configuration file.


    Boy, I hope I've missed the <sarcasm> tag on this one! It reminds me very much of the overuse of other methodologies such as "always code to an interface".

    I once inherited code from someone who always coded to an interface. So he'd often have IFoo, AbstractFoo, MyParticularConcreteFoo, and MyOtherLongNamedConcreteFoo all defined. But then sometimes, he'd have calls like this:


    IFoo foo = someObject.getFoo();
    Bar bar = ((AbstractFoo)foo).getBar();


    This came about because AbstractFoo was the
    only class actually implementating IFoo. Even worse was this one:


    IFoo foo = someObject.getFoo();
    Bar bar = ((TheOnlyConcreteFoo)foo).getBar();




    It was code like the above that made
    it IMPOSSIBLE for me to extend the functionality of the system without a total rewrite. At the highest levels, the original developer had said to himself "I've only got one low-level implementation, so I can use its behavior." Poor programming on his part, but inevitable.

    Too often, the layers of indirection in "code only to interfaces" or "always put everything in a config file" are pointless because there's only ONE target that is ever used. Even worse, they are dangerous because developers will inevitably start making use of the fact that there's only one target.

    Call it Freundlich's Law of Soft Coding:


    Use soft-coding where is it appropriate and necessary, and nowhere else.
  • Marc 2007-04-15 14:59
    > I always cringe when OTHERS cringe about
    > magic numbers. Sometimes, they're appropriate
    > (as you're pointing out). What's the point of
    > a mountain of defines or a config table that
    > includes obvious information?
    > #DEFINE NUM_DAYS_IN_WEEK 7
    > #DEFINE NUM_SECONDS_IN_MINUTE 60

    The point in that case is readability. If your code multiplies by a mysterious number 60, you will not know if that number 60 is to indicate the number of seconds in a minute, or the number of minutes in an hour. Same goes for the number 7, how do you know why the number 7 is used? When your code says DAYSPERWEEK instead of 7 it will be more easy to understand.

    As for the

    > #DEFINE ONE_MILLION 1000000

    This obviously adds no value whatsoever. In fact should its value change, that's another WTF. But what does the value one million represent? By contrast, #DEFINE MAXFILESIZE_BYTES 1000000 is perfectly valid.

    But the example you're giving doesn't have much to do with softcoding. #defines are typically not stored as configuration, so you would still have to rebuild and reinstall the system for your customer.
  • brazzy 2007-04-15 17:05
    Mandor:
    As someone who both admins and codes, I find this article horrifying. It sounds like it was written by someone who has the luxury of writing code and not actually maintaining systems and code over the long term.

    As someone who does lots of maintanance programming it sounds like it was written by someone who really knows how much stupid crap is done in the name of mainainability that absolutely kill said maintainability.
    First off, making everything configurable should be really "cheap." Most languages have some sort of framework for making things easily configurable. Even if your language doesn't have such, you will have to develop one for the cases that are inarguably hardcoding. Once you have an infrastructure for easy configuration, it should be really cheap to make everything configurable.

    If "everything" is configurable, your language is now an interpreter, and the configuration files are now the language you are coding in. You have wasted an enormous amount of time on something you could have achieved by choosing to program in a scripting language in the first place.

    Secondly, from a full lifecycle perspective, often the things that change are not the things that you anticipated upfront. The more things that are configurable, the easier it is to make changes during the lifecycle of the program. Sure, some changes will require a recompile, but by putting as much as is reasonable in a configuration file, you minimize this.

    You also minimize maintainability of the code. What kind of crap environment are you working in where compiling the code is so horribly difficult or dangerous or costly that it must be avoided an any cost? That the answer to "it's hard to tell which parts of the app may change" is "make everything configurable"? How about ditching that environment and migrating to a language where you can concentrate on productive work rather than the shortcomings of the environment?
    Also, as others have observed, in many environments, it's a lot easier to get permission to change a configuration than to change code. Code changes require careful testing, since coders tend to break things; config changes also require testing, but can be more easily backed out.

    Riiight. So in order to circumvent barriers intended to prevent code changes from breaking things, you propose to put the potential for breaking things outside the barriers and hope that you can reverse any breakage before it has serious consequences or anyone notices? I suppose if you work in a management-wtf-environment that can make sense...
    And also, "recompiling" is not always a simple matter. After N years, the compilers, tools, and platforms might themselves have changed, such that even recompiling original source might not produce new binaries that behave identically to the original binaries.

    If you're in a situation where a recompile of your project is a scary proposition that you'd rather not even attempt, you have a whole different magnitude of problem.
  • brazzy 2007-04-15 17:11
    Dirge:
    I'm sure it's often possible to get away with the sort of hackish, fast-but-crappy coding he promotes when it's internal to a company. It's still terrible.

    End users of a program should **never** have to change the source code and recompile just because data (like which states require a particular form) has changed. Source code gets lost. If you buy a product, you probably don't even *have* the source code.

    Congratulations on missing the point so completely after it has been explained repeatedly.

    The only beast worse than hackish, fast-but-crappy code is hackish, slow-but-crappy and unmaintainable code that increases complexity and project size with extra layers and abstractions that serve no purpose but trying (and failing) to turn logic into "data" rather than "code".
  • brazzy 2007-04-15 17:15
    Greg:
    You're thinking inside the box. There is a middle ground between a general purpose language (i.e. hard-coding) and throwing stuff in config files (i.e. soft-coding). That middle ground is a domain-specific language (DSL) which is used to generate code. You make it easy to write the business rules in a reasonably straightforward and natural way and make generating the code (and compiling it) part of the build system. As long as you don't try to make your DSL too big or your generator too smart, you're in good shape. It's still code, but it's code in a higher level language.


    A domain-specific language only has advantages when it can actually express the domain-specific things in a better (more concise, whatever) way than they could be expressed in the main project language. IMO this is rarely the case.
  • brazzy 2007-04-15 17:50
    eyrieowl:
    brazzy:

    No. The point is that if you really do a good implementation and follow through to the logical conclusion, you end up where you started: you're writing your logic in a fully-fledged programming language, changes need to be tested and you probably have a non-trivial deployment process.

    That's an unsupported assertion, one that I think is provably false. If you follow *your* logic to it's "logical conclusion", there is no point to any language other than machine language. After all, they're all just languages sitting on top of that. Clearly, though, higher levels of abstraction *do* have value and even you likely don't code machine code by hand. The point to any language that sits on top of a lower level of abstraction should be to provide useful abstractions that make doing common tasks easier. That's the fundamental reason why programming languages exist.

    Exactly. And we nowadays have a plethora of high-level languages to choose from. Why not use one of them them? Because it's more interesting to roll your own? Because your work is so very special that it cannot be adequately described in a general-purpose language?

    I never said there was no point in creating higher levels of abstraction, only that by putting those abstractions in "config files" then unless they are truely trivial and stay that way, you are in fact creating your own programming language which can contain bugs, needs to be tested, version-controlled, etc.

    It is definitely not the case that every problem requires a full-fledged programming language to solve. My example of computing an IRS 1040 is a perfect case in point. Externalizing the logic of the 1040 to a document that is read by a processor in _no_ _way_ requires a full programming language. The set of operations required is much more limited and specialized. So making an assertion that externaling logic leads inevitably to full-fledged-language-horror is just wrongheaded.

    Not being American I have no idea what kind of logic is required for handling that form, but I really doubt that the result of "externalizing" that logic was more maintainable than if it had been written as well-designed code in a general-purpose high-level language.

    eyrieowl:
    brazzy:

    And if you DON'T do it well, you end up with a hideous monstrosity of a language. Designing and implementing programming languages isn't really something most coders have a lot of experience in.

    Which entirely misses the point I made -- just because something can or has been done badly doesn't mean it shouldn't be done. You or someone you know might not be the best person to solve a particular problem, but that doesn't mean no one is qualified and should attempt the task. Most coders *I've* met are terrible system architects, but that doesn't mean there aren't *good* architects that you should have designing your system. Likewise, externalizing logic requires a certain skill and has an art to it--if you lack that art, don't assume everyone else does and that the approach is therefore flawed.

    Ah yes, the good old "you're stupid!" argument, so eloquently expressed.

    It is you who misses my point entirely. Just because something difficult, failure-prone and time-consuming CAN be done well doesn't mean it SHOULD be done when its benefits are questionable. What I am doubting is that there is any edvantage to "externalizing logic" over expressing it in an existing general-purpose language.
  • collector 2007-04-16 02:52
    #DEFINE ANSWER_TO_EVERYTHING 42
  • Richard 2007-04-16 15:53
    There seems to be a misunderstanding on which type of application each user's comments are about.

    I believe Alex's article was about a custom-built system for a single (perhaps up to 10) client(s), not a packaged program sold to millions.

    In such case, the "Application" is not just the executable, but also the configuration and probably the supporting enviroment at the client. The client does not care that the program does exactly what the configuration says, but that it does what it is expected to (include the correct documents for each state in this example). Testing that the configuration files or database entries are correct before deployment is just as important as testing the code.

    In my experience, clients almost never change any configuration files on their own anyway, even if they have requested something to be user-modifiable. Even if the changes are as "safe" as correcting the spelling of a translation string. Which suits us well, because we would have to fix any problems with misconfiguration.


    For packaged software the sweet-spot of user configurability is probably much more in the soft-coding direction, as users have no way of requesting features, and bear all the responsibility of maintaing their enviroment and configuration.
  • Jasmine 2007-04-17 17:34
    Yes, Amen brother! Thanks for writing this.
  • Paul 2007-04-24 11:53
    Wow, 179 comments and counting. Good show! Yet in all that I counted perhaps 5 mentions of the "user".

    This is not about "once and only once" .. .I think we all tend to agree with that.

    Alex's main point seemed to be that overly complex solutions (aka EBE) introduce more problems to a project than they remove.

    He argued (bravely) the KISS principle .. keep it in the code with really well tuned deployment practices.

    Fine ... to a point.

    But I think all this misses the real point:
    where you put your rules/configuration/data should ulitmately be determined by the required usage (both to read and write.

    This should be a discussion about the application of user-centered design in other words, and separation of responsibilities.

    Who is going to be responsible for the maintenance of that rule/configuration data? A programmer: sure, put it in the code. A system operator: hmm, maybe better put it in a config file. A user: web-based UI please, with AJAX;)

    In other words, there is no universal "balance" to be reached - it depends on your requirements and a good dose of common sense.

    Take an extreme case: the rules of arithmetic. 1 + 1 = 2. You don't expect to code/configure or define a business rule for what "+" means, do you? That is, unless you write compilers ...
  • Daniel 2007-08-28 18:03
    I wholeheartedly agree. While the quest for 'soft' code is admirable in intent, it is futile. The ultimate aim of developers who are fixated on 'soft' code is to create the perfect program - in essence, to endow the computer with intelligence. This is similar to efforts to create the perfect AI in a computer game.

    Their mission is - however - futile on machines which they would themselves acknowledge are actually incapable of independent thought and which they, despite their best efforts, are incapable of giving to them. (Thank God! I've seen the Terminator films!)

    Far better to acknowledge this fact, create code that does the job and forget about delusions of grandeur that imply that you are capable of making a bullet-proof piece of software.

    As you have already pointed out, the programming languages already developed were made to be flexible enough to create software suitable to the tasks we are confronted with. Attempts to utilise this software to create artificial application intelligence are a lost cause. If a specific application requires flexibility at the time, this can be identified and built in as required. But to try to make it future-proof is simply ridiculous especially when - in 2-5 years' time, the next version of my programming language will be released and my old code will no longer be compatible - nor worth adapting - anyway.
  • theodark 2007-09-26 03:47
    I agree with this article. I've found myself many times lost in the sea of this "soft coding" :)

    Just to point out some highlights:

    Of course you won't use defines like
    #define NUM_DAYS_PER_WEEK 7

    You do not need to reevent the wheel... On the other hand it would be silly not to
    #define PENDING_ORDER_TIMEOUT_DAYS 7

    or use

    if( m_order.getDaysSinceSubmission() > NUM_DAYS_PER_WEEK && m_order.status....

    instead.

    As for the hard-coded part: Even the most cleanest code has raw & dirty parts. We cannot avoid it and I personaly, am not against it as "part of the plan"! In fact because of "raw & dirty" code is why you have refactoring. In order to elevate and write more efficiently later on, parts of your app that are hard-coded.


  • Miklos Hollender 2007-09-26 07:24
    I'm always amazed by the fact how programmers don't understand each other. Alex was clearly writing about a mid-size (single db, single-UI) business app used only by one company. For this purpose this approach can be viable. Somebody else meant banks with security audits or software bought on CD's... for those obviously it cannot be.

    Hey! People! Why do we STILL believe that programming is ONE profession, and thus lessons learned on one field are easily transferable to another field? Frankly speaking, these debates look like as if a chemical engineer and a construction engineer would debate on how useful a given approach or device is.

    I'm personally in the same field as Alex, but I tend to like a bit of configuration, not in files though but on database tables shown on forms. The only reason is that it doubles as a succint documentation: if the customer says thingy A doesn't work and I cannot find a configuration option about it, I can search the code for where is that field used. Otherwise they aren't much use.
  • Bob Frankston 2007-09-28 15:55
    But there aren't 60 seconds in a minute! There would be if we didn't let astronomers trump reason by randomly adding and removing leap seconds.

    They are like fourth class programmers who don’t know that hardwiring their minor correction factor into our representation of time would make all time libraries invalid? It’s hard coding of the worst kind – they don’t understand the concept of representation and assume their definition of time is the only one that matters.
  • Arioch 2007-10-01 08:59
    tster:
    wrong, There are 7 days in a week if you are using a calendar that specifies that there are 7 days in a week. Indeed, calendars besides Gregorian calendar exist.


    Isn't the very term "week" became undefined (read: non-esxistent, senseless) beyond Gregorian (and other historically related) calendars ?
  • Arioch 2007-10-01 10:49
    [quote user="silverpie"][quote user="tster"]The last one to survive more than a year that used any other week was the French Revolutionary.[/quote]

    Wrong. It was 5-days and later 6-days weeks in early 1930-s in USSR.
    While Grigorian week was counted in parallel, all the economical life was scheduled according new weeks with no respect to legacy 7-days week.
    http://en.wikipedia.org/wiki/Soviet_revolutionary_calendar

    Captcha: cognac. Hmm, i think it was rather joint, that inspired creators of those calendars.
  • Alexei 2007-10-03 04:21
    what a shame, this term isnt on Wikipedia yet. Greate article
  • dotnetguy 2007-11-17 01:18
    dkf:
    Bell Endian:
    1 is 1 and 10 is 10 in big endian notation.
    It is in little-endian notation too, but it helps if you stand on your head or move to Australia.


    Don't pick on me, i live in Australia and make a living out of programming without having to know the details about bigEndian or littleEndian :P
  • CeilingCrash 2007-11-21 05:17
    Are you nuts !? Every magic value is a failure point, because it can change and then your code breaks. If you have 300 of them, you have 300 failure points.

    You can have them strewn throughout your code, or gathered at the top (constants), or in a database. These three possibilities are in descending order of accessibility.

    If you have hardcoded the number 32, say, the number of coke machines in your building, and they add another one - what are you going to do? search everywhere for '32' ? oh - and 31 in case of zero-indexed arrays? in hex too ?

    Will you be sure you got them all?

    Those magic numbers are your software's touchpoints to the world. They should be handled with great care, and gathered in an interface. Or else, you don't even know what values your code depends on! You will live to regret any magic value in your code.
  • Andy Skuse 2008-01-27 15:38
    AN:
    You know, we are so far down the road of soft coding that it would blow your mind, and it works for us. We have a couple of dozen clients, and they all have custom data, different versions of forms, and different business logic. We don't have massive code forks for these clients, we just configure the bejeezus out of the application.

    Our ORM model is configurable. Our business logic is configurable. Our presentation model is configurable. All of this is runtime loadable, and we edit the configuration data with more or less the same tools that our clients use to edit *their* data. We store all the data in the database, right alongside the application data.

    Yes, there are serious risks and problems associated with this methodology. But given our scenarios, the alternatives are worse. And by maintaining configuration metadata for everything, we can support both a Windows desktop client and a web client without coding all our customizations twice. And when a client asks for another label to be changed and for more alterations to the process flow, it doesn't require us to mess with the overall source tree and we don't have to go through a complicated deployment process -- we don't even have to recompile!

    The moral of the story: badly-thought-out softcoding is bad. But badly-thought-out *anything* is bad. Don't be afraid to use advanced, potentially-messy techniques in your code base. But only use them if they make sense for your situation, and prepare yourself for the landmines that come with that approach.
  • soru 2008-02-27 14:52
    na:
    I would much rather update a row of data (a dollar amount threshold, for example, from 20,000 to 30,000) than to have to make a code change, get approval form 3 managers and a vp, go to a change control meeting, and then move the change through test, qa, then to prod.


    UPDATE business_rules_table_095
    SET trading_exposure_limit = 999999999999
    WHERE user_id is "Kerviel";

    Making business-critical values configurable in order to bypass a change control process is not without drawbacks.
  • China 2008-03-05 19:37
    That really depends on your definition of what a configuration file is. I would separate the configuration files into those that the user touches and those that they don't, and put the latter into a directory/regestry entry/etc called NOT_USER_MAINTAINABLE or some such.

    Give customers a tool to change the files with, if you intend to let them change the files. Even if it's just a text editor it'll make them think twice, and you should code it to restrict changes to the files you want them to change.

    Any customer has to take responsibility for their configuration changes, as set out in their license and service agreements. E.g. we use Oracle; if I make changes to any of the dozens of config files lying around the place I wouldn't expect Oracle Customer Services to bale me out when the database dies, I'd expect to revert my changes from the files stored in Subversion/CVS/etc.
  • moses 2008-04-24 09:06
    i'd like to learn how to code it.
  • Uchuu 2008-07-15 12:16
    I dont get get it:
    Why is "seconds = minutes * 60",
    read
    "seconds equals minutes times sixty"
    less "readable" than
    "seconds equals minutes times num_seconds_in_minutes"?
    those many, many constants just obfuscate what your code is really doing.
    If I am the reader of you code, if I want to understand and/or debug it, I have to "decode" the constant into the numerical value. I remember the example:
    someVar % NUM_DAYS_PER_WEEK == TUESDAY
    What if you somehow made a mistake there, that in your code you normally count the days from monday, but here from sunday?
    If I want to find this error, I have to follow the calculation - easier with numbers or with constants?
    There are very very good reasons for constants in the code, no doubt about that, but "one time constants" are sometimes, maybe on rare occasions, better of in the code with a comment aside them.
    "seconds equals thirty (minutes) times sixty" is easier to follow than "seconds equals thirty (minutes) times num_seconds_in_minutes"

    Well, on the subject itself:
    As far as I understood, like any programming technic, avoiding hard coding is good - if not taken to far. When it's taken to far, making things no longer better, but worse, Alex calls it "soft coding"
  • anon 2009-02-12 07:57
    Actually this is an excellent example why you shouldn't write something like

    enum { BILLION = 100000000 };

    Three consultants out of four probably cannot be bothered to look up the definition of BILLION. On their last day, they'll hear on the grapevine that this code came from the other side of the ocean, hopefully realizing the implications on their way home.

    Then again, there's a 50% chance your consultant will write 1000000000 anyway where he should have used BILLION, so when the definition of BILLION changes, you're hosed anyway.
  • Björn 2009-02-17 09:56
    "Seriously, I think it's okay to use magic numbers in this case. I honestly don't see the need to have to change these any time soon."

    It is not about being able to change to numbers, but also about code readability. DAYS_IN_WEEK says something about why there is a "7" in the code.

    Obviously it still can be overdone, as in your ONE_MILLION example.
  • rene___ 2009-02-17 19:47
    Very nice article.

    It's nice to read about stuff you go or have been through yourself.

    I agree to the people who wrote that writing boring applications - according to your specifications - shouldn't have to be boring.

    There will always be the possibility to pursuit perfection, it's only defined in another mater.

    The comments on the article were getting pretty nerdy, if you ask me. :-)

    Greetings,

    René Vaessen.
  • DeeJay 2009-02-18 03:22
    I respectfully disagree. Number values surely aren't subject to localization? Surely you wouldn't write something like :

    if (population_of_country) > ONEBILLION
    ...

    The business rule calls for a value of 1 000 000 000 which is the same whatever nationality the developer is.

    And if you were going to start defining a constant for ONEBILLION would you then need to define constants for TWOBILLION, THREEBILLION ....

    There should never be constants defined like this. If someone only types 5 zeroes when they meant to test for 1 million, then that's a bug which should be caught by testing.
  • Old Fart 2009-02-18 21:13
    Mr Steve:
    This article really gets to the heart of 'art of coding', that is finding the right balance between:

    saving time and money now (hard coding)

    vs

    saving time and money later (soft coding)


    for whatever weird reason, coders generally think in terms of soft coding and making great frameworks that will change the world! (just look at how many ajax frameworks and javascript form frameworks there are currently out there).

    that's only one side of the art

    people (publicly at least) say they dislike hard coding and hacks. personally i think that they're great. alot of the code that you currently write is for products that have a half life of less then 2 years. often there's no reason to abstract the hell out of your code cos your product will get binned and replaced, so your abstraction is simply a waste of time and energy.

    so it's important to be mindful of this and go for balance.


    i love u. r u still looking to have babies?
  • corlettk 2009-04-30 02:33
    One common concern which this article did not address is the requirement to maintain distinct different versions of the business-rules over time.

    Such "hardcoding" is wonderbar if all you have to worry about is today (i.e. OLTP). However, if you need to maintain multiple versions of the logic (for different aged contracts, for example) you need to softcode everything, and I do mean EVERY single THING.

    Yep, that way lies maddness, but it's still better than the alternative... can you imagine maintaining every released version of "business rule" concurrently?

    Now there's a lovely bowl of petunias.

    Cheers all. Keith.
  • corlettk 2009-04-30 03:19
    RaspenJho wrote: Someone had to do it....

    Oh goodie! Now we've taken the perfectly comprehensible


    private void attachSupplementalDocuments()
    {
    if (stateCode == "AZ" || stateCode == "TX") {
    //SR008-04X/I are always required in these states
    attachDocument("SR008-04X");
    attachDocument("SR008-04XI");
    }

    if (ledgerAmnt >= 500000) {
    //Ledger of 500K or more requires AUTHLDG-1A
    attachDocument("AUTHLDG-1A");
    }

    if (coInsuredCount >= 5 && orgStatusCode != "CORP") {
    //Non-CORP orgs with 5 or more co-ins require AUTHCNS-1A
    attachDocument("AUTHCNS-1A");
    }
    }


    and turned it into XML... which ain't so comprehensible...

    <SUPPLEMENTAL_DOCUMENTS>
    <CONDITION TYPE="stateCode" VALUE="AZ" OPERATION="=">
    <ATTACH DOCUMENT="SR008-04X" />
    <ATTACH DOCUMENT="SR008-04XI" />
    </CONDITION>

    <CONDITION TYPE="stateCode" VALUE="TX" OPERATION="=">
    <ATTACH DOCUMENT="SR008-04X" />
    <ATTACH DOCUMENT="SR008-04XI" />
    </CONDITION>

    <CONDITION TYPE="ledgerAmnt" VALUE="500000" OPERATION=">=">
    <ATTACH DOCUMENT="AUTHLDG-1A" />
    </CONDITION>

    <MULTICONDITION>
    <CONDITIONS OPERATION="AND">
    <CONDITION TYPE="coInsuredCount" VALUE="5" OPERATION=">=" />
    <CONDITION TYPE="orgStatusCode" VALUE="CORP" OPERATION="!=" />
    </CONDITIONS>
    <ATTACHMENTS>
    <ATTACH DOCUMENT="AUTHCNS-1A" />
    </ATTACHMENTS>
    </MULTICONDITION>
    </SUPPLEMENTAL_DOCUMENTS>


    ... and we've moved those pesky hardCoded values to a hardcoded mapping method ...


    object value =
    cond.Type == "stateCode" ? data.StateCode :
    cond.Type == "ledgerAmnt" ? data.LedgerAmnt :
    cond.Type == "coInsuredCount" ? data.CoInsuredCount :
    cond.Type == "orgStatusCode" ? data.OrgStatusCode :
    string.Empty;


    Wonderbar! All we need to do know is write our own XML rules-mapping code-generator! ... and of course we'll need an rules-editor application to make that "XML programming language" look more like Java.

    This way lies madness.... Please don't do it, unless you have a requirement to do so, such as maintaining a history of the business-logic, allowing you to repeat a particular process as-per the rules which where in effect at that time.

    Signed: The humble maintenance programmer.

    Cheers. Keith.
  • David 2009-05-22 14:21
    Hello there,

    my colleague always says: "I good developer is a lazy developer". Sure thing from my point of view.

    Two examples from two different customers:
    1) Customer: "everything has to be parameterizable within the database"- so we coded our solution that way.

    First deployment: July 2002
    First test if the did it right (customer changing some button texts and stuff): August 2002
    Since then? Nothing- a lot of work (development and testing) for nothing- so much for mandatory configuration *gg*

    2) Customer: "We want to change the labels and translate them into different languages". Our developers did their best and we ended up in about 2000 lines of xml-config. Guess what- the customer was not able to alter the right entries and therefore _we_ are changing translations and including them into subsequent releases of the software.

    The point is- depending on the customer and the size of your project- be reasonable and do not use config because "software is done that way nowadays"- it isn't. Software ist supposed to solve problems, kept simple and mainly cheap (minor changes causing tons of money to be spent will tend to disappear- so there are no changes at the end of the day).

    Why do we have that much frameworks, tools and scripting languages? Because writing software without something exciting and new is not interesting for the usual developer ("been there, done that")- so as long as you have this "proud" thing within development ("sure I can use O/R-Mapper X, but I need this and that and can code it in the same amount of time, I have to learn the API"), there won't be any substantial progress.

    We are defying the same programming and design errors as our fathers did in the 70s, don't you think so?

    At least I have no solution for this- maybe there is not (at least no deterministic ;-))).

    cheers
    David
  • golddog 2009-06-05 10:24
    I think what Alex is strying to say is a good thing to keep in mind when developing: don't solve problems that don't exist.

    For the example he shows, sure, when another state comes on, or we need to change the document type for one state, or something, we might revisit this process and rewrite it. Maybe we configure a list of states that need 048X and 048XI and check against that.

    But, the fact is, these are the requirements. Don't make things unnecessarily complicated when there's not a legitimate reason to.

    Some of the examples remind me of a developer at a previous employer who wanted to make everything "enterprisy". We used to joke that he would argue we'll probably colonize Mars some day, and since the Martian day is 39.5 minutes longer than the Earth day, we should allow for that difference in our code now. (Not as far from some of his arguments as you might think).

    The point is, you make you best guess at the likelihood of change, rather than blindly add complexity. If you find later that these conditions really are pretty dynamic, it's just software, go ahead and refactor at that point.

    It's great to anticipate potential problems, but don't assume complexity where there really isn't likely to be any.
  • mzamora 2009-06-06 02:09
    I haven't read the five pages of comment (and I won't), but I'm just going to add how I see the whole hard vs. soft coding through my experience with pretty complicated software: financial services software that encode how to do business with all kinds of weird financial instruments, which are full of arbitrary rules and exceptions, which nevertheless can (mostly) be represented as soft code.

    Hard code is OK when the rules are few, they don't change frequently, and the process is OK with involving the developer whenever a rule has to change.

    Soft code should be used when any of the above conditions can't be met.

    For example, picture the little 300-line hack evolved into the 50-file, 35,000-line monster in the course of four years. In this case, hard code is the main cause of bugs and broken business processes that cause 2:00AM calls to wake the comatose developer sleeping under the desk.

    When the business rules in the application reach a certain level of complexity, a new level of abstraction can generally be applied to organize the rules. Then it's time to dump the old app --or the parts of the app that encode those rules-- after developing a new way to soft code the business rules which makes it more maintainable.

    90% of the cases can be represented with soft coding without resorting to generalized data structures which are so over-designed that they turn into abstract exercises in intellectual onanism.

    The really weird cases must be relegated to hard code, and if possible, should be done with code running in a sandbox that accesses the business data through a strictly defined interface.

    Perl comes to mind (using anonymous closures), EJBs, Java stored procedures, etc.

    In a nutshell, soft code can take care of the huge majority of rules in an efficient, maintainable manner. Hard code should be used with the exceptions, but that hard code should be isolated both in the build process and at run time, and closely tested and monitored (unit testing, sandboxing, etc.) to ensure correctness because they will be the source of most of the insidious bugs.

  • veggen 2009-07-20 16:49
    Ummm... There's really no "soft/hard code" dilemma here. Have you heard of Drools? Jess?
    There are times when you can't avoid changing the code, but this is not one of them.
  • da nigga rie chea 2009-09-15 22:51
    does zero really exist? does seven even exist? let me check my bible. . .
  • c2d 2009-11-19 21:28
    Actually your comment proves the exact opposite. If there are several definitions for BILLION, using it as a constant would surely create confusion.
    Consider x = 60 * ONE_BILLION, what's the answer?
    Is it 60 000 000 000 or 60 000 000 000 000?

    Now consider x = 60 * 1 000 000 000.
    What's the answer here?

    So whatever you call that number, we can agree upon it's numeral expression. But if you used a define as suggested, we may expect entirely different answers and just end up talking past each other.
  • oksupra.com 2010-06-19 03:09
    Supra shoes are so popular all over the world. Whatever you take on Supra being in the Supra Skytop Shoes market. Now Supra Strapped Shoes also very popular attention. It is nice that they actually took the time to make Supra Skate Shoes that work well. Supra shoes is a brand that has been inspired, designed and marketed by passionate individuals. We have brought to you the fullest selection of Supra footwear at cheapest price.


  • xiaokj 2010-08-18 14:13
    Reading the scary full 5 pages, it is quite weird to see that Alex had been mostly absent from this forum debate. I hope to see a follow up.

    I belong heavily in the soft-coding side, but I agree that this is in the grey area up for debate. Neither end is worth pursuing to their logical conclusions.

    I think it is better to think of development methodologies. Agile methods would prefer hard-coding prototypes, and when the need arises, expand it into soft-code. Some other methods would argue for the other direction.

    Although I would very much prefer soft-coding, I can see where the Agile method is hinting at, and I agree with that. However, I will only agree with the prototyping phase (or project is too small to warrant anything other than a prototype). Once the underlying method is working, I think I would rather see it soft-coded, albeit just a little bit.

    After this huge amount of unsubstantiated opinion, let me add some meat to my argument.

    If you see soft-coding as optimisation in the rule modification process, then you can clearly see how unwarranted huge architectures in soft-coding is premature optimisation. It is more important to make sure that your internal code structure works before you think of constructing your soft-coding behemoth.

    Take the case of sendmail. It was born in a time when UUCP was the norm and each pre-network had its own mail syntax (the @ symbol was yet to be). As such, it had to soft-code the network characteristics in its configuration file or hard-code hundreds of cases. Common sense mandated the former, and culminated in the configuration mess. Later, it would be the same configuration mess that would doom the project against rivals -- the @ sign just gained traction.

    However, if sendmail were not extensible, the internet would have had trouble forming because mail would not traverse borders. Not to mention that its extensibility allowed for experimentation with design, finally leading to the @ sign standard. The lesson to get is not that soft-coding is bad, but rather that extensibility needs taming, and that standardisation is important.

    On the other end of the spectrum, look into the Art of Unix Programming Chapter 9 on Data Driven Programming. The preceding introductory chapters talked about complexity -- humans have trouble with complex algorithms, but are good at handling complex data structures. When the correct data format appears, the problems at coding solve themselves. Then, as promised, it expands on the idea in Chapter 9 with case studies, 2 of concern to the problem at hand are ascii and fetchmail.

    Ascii is undoubtedly the most beautiful representation of simplicity in algorithm and code, yet it is entirely soft-coded. And the soft-coded part is entirely compiled and hard-coded into the binary -- the scope for changes is low enough to warrant that.

    Fetchmail example, on the other hand, talks about using formal parsers to handle configuration, and the implementation genius is to, instead of copying another instance for the configuration-helper, use the nicely created parser for the main program to dump the parsed config for the helper. Centralised nice code without increasing complexity much.

    It is clear that both sides are capable of monstrosities. Sendmail is a real disaster in its early days, but at least the disaster is mandated by necessity. However, it does not mean that soft-coding is inherently more complex than hard-coding -- ascii shows how the opposite can be the case, given clever coding.

    I suppose we need to agree, on the other hand, that the example stated by Alex is horrendous. State laws are notorious to political whims and hence tend to be messy. If each state has 2 random demands, 20+(? I am not American, and I cannot be bothered to research minor details) states will mean 40+ overlapping conditions to code for. Slow-moving regulations will make it horrendous to push out changes in hard-coded values. A more sensible approach would be to cleanly separate out the state laws and allow for specialists to formally produce the configurations required, and send that out. Following the ascii example, it can be compiled, albeit into a module/internal state instead of the whole program. Flexibility as is required can be arranged for. Making it part of a database would, in this case, be uncalled for.

    Nevertheless, the underlying idea that there is a limit to soft-coding is correct. Sendmail is my replacement example. Too much flexibility is also trouble for testing. Each binary yes/no option doubles the testing load -- exponential increase so that 10 options creates additional 1024 test cases!

    As many had already said, we need some form of balance, and I suppose hard-coding a prototype is more than justified. If the prototype is more than satisfactory, there will be no need to soft-code. However, if some internal and variable threshold is overcome, soft-coding is much better. Especially when you find yourself repetitively apply fixes -- the codebase that needs repetitive fixes is more likely the source of the problem itself.

    Now for some of my own attempts at the forum digression.

    #DEFINE DAYSinWEEK 7
    is horrendous-looking, but will save you when you realise that you actually meant WorkDaysInWeek 5 or 5.5 -- a global search and replace DAYSinWEEK to WORKdaysINweek is a lot easier than looking through for 7s all over the place. Happened to me.

    #DEFINE SEC_IN_MIN 60
    is probably sadder than what I propose:
    seconds = minutes * 60 // 60 seconds in a minute
    i.e. I propose comments for this purpose -- constants extremely unlikely to change at all. This is because you might want to do it with undecipherable variable names as shown above with the object-orientated code -- suddenly you cannot even see that you are dealing with seconds and minutes when you have to navigate through the object structure.

    MILLION and BILLION should be 1E6 and so on, with comments on why you are using them that way, as in the case above.
  • x-sol 2010-11-08 16:15
    The Enterprise Rules Engine Revisited

    Why does the word RETS keep going through my head?
  • DriverDevel 2010-11-13 05:07
    Cotillion:

    Always program as if the person who will be maintaining your program is a violent psychopath that knows where you live.


    If you obfuscate your code to its fullest, then he'll never be able to figure you out anyway ;)
  • anniepoo 2010-12-23 22:51
    One extreme version of this (or perhaps a separate antipattern) is localization.

    Instead of the perfectly clear

    printf("stop\n");

    you get
    printf(__(STR732));

    (I'm not kidding. that was the standard at a certain fortune500 company).

    whenever possible I try to get 'stuck' with the job of localization so I can do the obvious thing - write a little preprocessor that replaces "stop\n" with "alto\n" driven by a file.
    I've heard the objection that people might want to translate 'stop' into different words by context - in which case make it

    printf("stopTHINGTOKEEPDOORFROMSWINGING\n");
    and
    printf("stopPUTONTHEBRAKES\n");

    and run the american english version through a 'translation' as well.

    There's a general tendency for software engineers to be 'pound wise and penny foolish' - looking for optimizations in large and complex cases like needing to change a constant in context while ignoring simple needs like the need for the programmers to understand the code.

  • Anonymous 2011-04-05 22:22
    That's actually a really good example.

    The simple scripting language in Steam Source games might not even be turing-complete, but the scripts allow a wide variety of customization.

    Want to make the game entirely playable without a mouse?


    bind j +left
    bind l +right
    bind i +lookup
    bind k +lookdown
    etc...


    Imagine if this philosophy were used for stuff like text editors.

    "Hmm, I use double-underline bold font a lot..."


    bind "ctrl shift d" "toggle-bold, toggle-underline"


    Yes, scripts are ''very'' useful for this sort of thing. They let you change not only a few constants, but the course of the entire program, just by editing a few text files.
  • Anonymous 2011-04-05 22:53
    GOF was, and never will be a WTF.

    The fact that half of them would be unnecessary with a decent metaclass or prototype system is a WTF.

    More related to your comment, the fact that everyone ignores the "drawbacks" section when deciding whether or not to use a GOF pattern, is a major WTF.

    Something tells me that IDocumentAttachmentStrategy's implementors would take up way more LoC than a simple if/else chain.

    And it still wouldn't be user-customizable. Unless they had a decompiler.
  • JackSchitt 2011-06-18 23:12
    I've had to do something like this previously. The gotcha was that the business logic HAD to be in a separate file (as per the spec) which would be periodically updated by some manager separate from the deployment of the app.

    The 1.0 release used windows scripting host. The .rules file was basically a .vbs file with functions that would be called by the app.

    They decided (after something like 10 years of use) that editing rules in notepad was unintuitive and error prone. I took this time to migrate everything to .Net and now the .rules files are compiled the first time they are needed. The best part is that you can write the files in the VS IDE with intellisense.

    It works, and it works well. If a rule needs some piece of information not provided by the standard params for that function, it can access the database as needed. There was even one case where a rule would consult an email inbox to determine it's course of action (it was for a special promotion where you had to email the company to take part).
  • Susan 2011-10-11 18:26
    Yeah, but this is missing the point. I'd prefer to read:
    if (x < NUM_DAYS_IN_WEEK)

    than
    if (x < 7)

    because it explains the 7.

    You don't just have constants so you can change them, or to help you remember the value. It answers the question "WTF 7?".
  • Powerslave 2011-11-12 23:53
    Yup. And I surely want to rebuild 40k+ file application just to change which particular document is linked with a given state or amount...
    So-called configuration files did not emerge without a good reason.
    You just need to find the correct balance.
  • Nagesh 2011-12-01 13:19
    This is interesting article
  • Nael Mahfouz 2011-12-29 07:58
    I liked your article very much. I disagree with nearly everything you have said but I think the article shows a lot of evenings trying to figure out bad soft coding.
    The example you have provided is very simple and I agree that creating some form of business enterprise rules engine to handle this is overkill.
    Your final paragraph is the ultimate in soft-coding. It is all about using metadata to reduce complexity, regression testing and code fragility to programmatically compile solutions.
    There are intermediate solutions as well. Any code element executes an input, processing and an output.
    If you factorise out the common denominators of these code elements in any given piece of work, normally there are only a few elements.
    If sensible rules-driven metadata are used to describe the input, operation and output of the handful of code activities then the code remains relatively static (until new functionality is required) while the metadata changes need only unit/integration testing and automatically regression tests the code.
    Finally, "soft-coding" allows you to reduce the amount of development from the product of variables to the sum of variables. If there are ten code elements with three operations each, there are thirty portions of code. With softcoding, there are only three pieces of code and ten pieces of metadata equalling 13 instead of 30 development activities. When you multiply this by several hundred times, the savings become enormous and the quality of the soft-coded codebase becomes impressive.

    Where soft-coding falls down is lack of analysis and the use of convoluted and difficult to understand metadata. This is what I believe you are describing. But in this case the map is not the territory.

  • toshir0 2012-05-29 10:25
    *Brrrains*

    (for Akismet, spamming and pointless-thread-rezzing are the same, maybe ?)(if so, -1 shame point for this rotten pile of sh... brilliant software.)
  • Ross Presser 2012-05-29 11:38
    The advantage of sticking by rules like "Everything in moderation" is that you get to point your finger at anybody you like, saying they're being immoderate one way or another, without having to back up your statements.
  • TJ Powell 2012-08-15 04:26
    Speaking as a requirements expert - that would indicate that the "requirements" were simply not well-thought-out and written correctly to begin with. The current popular paradigm is start coding as quickly as possible, and change things as details emerge. Emergent "engineering". This is like building a house without a firm, well-constructed blue print - and leads to the same result. Chaos.
  • TJ Powell 2012-08-15 04:31
    It means, common sense must be deployed with respect to the amount of abstraction. Benefits and expense must be weighed in each case. Sometimes, when reuse is called for - a higher level of abstraction and runtime configurability makes sense. Most often, it is easier to simply write the code. I've worked on EXTREMELY complex space systems - and almost all the code is done inline. For a reason. Because a person can immediately look at the code and determine what it does. Sustaining engineering costs are always higher than original development. So that is where the emphasis in large systems should be. Far above any concern for "elegance" - which is more often than not, a euphemism for convolution. I still believe that many programs enjoy writing code that others have difficulty understanding. I attribute that to an ego malfunction.
  • TJ Powell 2012-08-15 04:42
    And I will further comment that most "interfaces" as currently defined, are often useless and indeed, confusing. The assumption of an immutable interface, where only the code changes MIGHT work if the system was well-thought-out, and planned to last for many decades in terms of reuse. But in software, this is almost NEVER the case. I've made a living coming in and cleaning up interfaces that were broken. Broken by inevitable change. (And I'm talking about repeated changes to the interface signatures themselves - See Microsoft). I get paid lots and lots of money to come in and clean up code written by developers who prize academics over productivity. At the end of the day, I actually get paid to throw out lots of unnecessarily abstract code - and write code that is maintainable, meets the requirements and eliminates crazy levels of complexity. Many of the "modern" paradigms have been created in academia by folks trying to sell books, and marketing departments trying to create a "brand".
  • TJ Powell 2012-08-15 04:50
    I define my state machines and transitions in a global module, in HARD CODE (so to speak). Not in a config file or database. If the rules change, I rewrite that piece of code and republish. Most of the time the users don't even see the change. It takes 20 minutes to rewrite, test and publish. And everyone who works on the system knows exactly where to go to find the data structure (one!) that defines the legal transitions. Since it is shared code, and it not splattered all over the database, it's simple - not accessible to the user, and we have readable, controllable, affordable and simple code to maintain. That is why one person (me) can write 800K lines of commercial code in less than 3 years, and sell it at a profit.
  • UnkownDev 2013-07-02 10:34
    What I tend to do is hard code stuff that's unlikely to change.
    When I'm not sure if it's unlikely to change or when it's not easily understand it I just write a little comment.

    Unless I use it several times, then I create a variable with a meaningful name.

    I tend to put values into variables instead of soft coding, figuring I will have to change the code anyway but by using variables it's quick and easy.

    Soft coding is a great idea when applcicable, e.g. the amount of orders needed for a customer to get bonus points on the other hand things like statecode "AZ" is not likely to change in a long time, so you could just hard code it.

    However, things like laws are a grey zone because laws tend to change.
  • John C 2013-08-09 10:17
    This article, seems to me, to be mostly nonsense. If you have a DB, you can create one generic table that has a ElementID in it so that you can softcode all sorts of values that otherwise require coding changes. You can even build a maintenance program to allow admin users to update these values.

    Our company has been using this method for decades now, and it continues to be a valid, flexible technique that is good for customers/users & programmers. It indeed, significantly reduces the need for programming changes and additional deployments.

    I hope nobody follows this advice.
  • ThunderGr 2013-11-02 09:46
    Putting numbers into constants it is, still, hardcoding. Constants are meant to provide readability to the code *and* make it easy to change a value used in several places in the code, without missing any.

    Softcoding, as described in this article, is *moving the values from the source code to an external medium(like a file or a database) that will be read from to a variable*.
  • Rob Martins 2014-02-13 06:46
    Argh! I think there is a very careful set of decisions to be made around the creation of supporting sub-systems that handle logic, but the basic strategy is sound and part of an established philosophy of separating concerns.

    As a Chief Architect I abhor the notion of cramming everything into one system. Stratify and give clarity to the purpose(s) of the system. We do it all the time. We have a presentation layer, a data layer, a business layer.
    Some developers can't handle separation. They think everything should be in one place. If that's the case go back to one project solutions and see how you get on. It's crazy to work that way and smacks of poor experience. I simply can't fathom why anyone would not appreciate the elegance of sub-system that has a clear, central function. This means a developer can focus on the UI or Data without worrying about other parts of the system. It also protects more sensitive or technically complicated areas.

    If the intent of a system coalesces into a distinct form, it is sensible to separate. That includes exposing common problems. Therefore if your logic is crammed into page(s) - and it is littered with IF THEN and magic numbers and order precedence is all over the place then you're doing something wrong in my book and ultimately making it harder to maintain. That code will become a mess. It might be easier to cut a first draft but you're kidding yourself in the long-term.

    So, whenever I see a mass of logic on a page I cringe (you're right) and I think to myself surely you must have considered a system that does that work for you? Surely you can see that as the system grows, that code will become a mess.

    The other factor I see daily is developers who plateau systems out because they either don't know that a supporting system could be created or they if they do, they consider it to be too abstruse to create one - they're not sure how. However, that doesn't mean it's a bad idea. It depends on what that system does in terms of supporting the development. If the end result is reduced effort in creation and maintenance of a system then it is worthwhile. That maybe be hard work but does not mean because you can't do it it's a bad idea. True some can't use the system either but again is that because it's a poor system or simply that they're not experienced to work with a formal logic sub-system. Maybe the sub-system can be made easier to consume.

    Ultimately I want a developer to simply write less code and the configuration be as easy to maintain as possible. I don't see that creating a separate system that can handle logic necessarily means these things can't be achieved.













  • Rob Martins 2014-02-13 06:48
    I completely agree. I think it was written by someone who doesn't get architecture.
  • Daniel Tress 2014-02-14 05:34
    Possibly the worst message you could give a new developer.
  • Nic Battler 2014-02-14 16:20
    I disagree completely.