- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
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.
Admin
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.
Admin
for a second I that you were meaning What The F...
Admin
What does this article say about that well-known mail transfer agent, sendmail? Perhaps the most soft-coded application I can think of.
Admin
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.
Admin
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.
Admin
Admin
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.
Admin
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
Admin
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.
Admin
Can't we all just get along? :D
Admin
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").
Admin
Great instructive article please have more of these.
Admin
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.
Admin
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.
Admin
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 ;) ).
Admin
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.
Admin
[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
Admin
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.
Admin
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:
changing a line of code that reads "if foo > 12345" to "if foo > 54321"
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.
Admin
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:
This came about because AbstractFoo was the only class actually implementating IFoo. Even worse was this one:
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.Admin
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
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.
Admin
Admin
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".
Admin
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.
Admin
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.
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. 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.
Admin
#DEFINE ANSWER_TO_EVERYTHING 42
Admin
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.
Admin
Yes, Amen brother! Thanks for writing this.
Admin
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 ...
Admin
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.
Admin
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.
Admin
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.
Admin
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.
Admin
Isn't the very term "week" became undefined (read: non-esxistent, senseless) beyond Gregorian (and other historically related) calendars ?
Admin
[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.
Admin
what a shame, this term isnt on Wikipedia yet. Greate article
Admin
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
Admin
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.
Admin
Admin
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.
Admin
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.
Admin
i'd like to learn how to code it.
Admin
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"
Admin
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.
Admin
"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.
Admin
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.
Admin
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.
Admin
i love u. r u still looking to have babies?
Admin
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.