• Marcin (unregistered) in reply to MRK
    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 (unregistered)

    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 (unregistered) in reply to chrismcb
    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 (unregistered)

    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 (unregistered)
    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.

  • (cs) in reply to qbolec
    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;" <p>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.

  • (cs) in reply to Doug
    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 (unregistered) in reply to chrismcb
    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.

  • (cs) in reply to phs3
    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 (unregistered)

    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 (unregistered)

    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 (unregistered)

    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 (unregistered) in reply to Morgan
    Morgan:
    Greetings, 'Just do another build and deploy' (to paraphrase) is absurdly simplistic.

    Mod parent up... oh wait this isn't slashdot.

  • OSE (unregistered)

    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 (unregistered)

    What about the dreaded Change Control Policy?? That tends to make rolling out the code changes a bit of a headache.

  • m23 (unregistered) in reply to chrismcb
    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 (unregistered) in reply to MRK
    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

  • (cs) in reply to mbvlist
    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 (unregistered)

    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 (unregistered) in reply to chrismcb
    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 (unregistered)

    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 (unregistered)

    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.

  • (cs) in reply to joe_bruin
    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 (unregistered)

    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

  • (cs) in reply to kanna
    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 (unregistered)

    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 (unregistered) in reply to qbolec
    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 (unregistered) in reply to Justin Buist

    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 (unregistered)

    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 (unregistered)

    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:

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

    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 (unregistered) in reply to Mr Steve
    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 (unregistered)

    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 (unregistered) in reply to vt_mruhlin

    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 (unregistered)
    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 (unregistered)

    {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 (unregistered)

    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 (unregistered)
    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.
  • (cs) in reply to eyrieowl
    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 (unregistered)

    You're writing business logic in code? Use a system where you can model that stuff.

  • (cs) in reply to chrismcb
    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?

  • (cs)

    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 (unregistered)

    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 (unregistered)

    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.

  • (cs)

    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 (unregistered) in reply to Isuwen

    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 (unregistered)

    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 (unregistered) in reply to joe_bruin
    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 (unregistered) in reply to Bell Endian
    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 (unregistered) in reply to ifthenelse
    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 (unregistered) in reply to Saladin
    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

Leave a comment on “Soft Coding”

Log In or post as a guest

Replying to comment #:

« Return to Article