JFHCIThe evil that is configuration
Chris Ortman asks a very good question about my just hard code it post:
I really like the simplicity of the approach, but does this impose a requirement that in order to change the discount percentage of the system I must be able to write c# code? I think it would not take very long for someone to ask me for and 'admin' screen to do that.
I run into this all the time with new features that would be trivial to implement if not for the database table to hold the settings, the model to work with the table, and the admin screen to edit it. How do we get from 'enter 5 into this box in the admin screen' to write class that applies the discount percentage you want .
I have a very simple answer for that. You don't provide any sort of admin screen, and you don't provide any way for a business user to go into the system and make a change. To start with, the system administrator has no idea what are the implications of changing such a configuration. Next, we have the standard issues of when we reload the value, validation, etc. All sorts of things that we really don't want to deal with unless we have to. Not to mentions that the idea of letting anyone the option to modify operational parameters without regard to testing and QA makes me very unhappy.
All of those are workable with enough effort, however. What is not workable is the end result of such a system. Here is what you'll end up with:
Remember, we expect to have a lot of such rules. So we expect to have a lot of configuration values. And don't get me started on reusing configuration values for different purposes, just because a dev saw something that looked even somewhat similar to what they were doing now.
Given this piece of code, then, how are we going to handle a changing business condition? Let us say that we want to offer this only to preferred members after the first 6 months:
public class DiscountPreferredMembers : OnOrderSubmittal { public override void Execute() { if ( User.IsPreferred ) Order.AddDiscountPrecentage(5); } }
This is trivially simple:
public class DiscountPreferredMembers : OnOrderSubmittal { public override void Execute() { if ( User.IsPreferred && DateTime.Now > User.PreferredMemberSince.AddMonths(6) ) Order.AddDiscountPrecentage(5); } }
Compile this rule (which will usually be in a separate project, along with a bunch of other tightly related rules) and push it to production. If you are doing an out of band release, you might want to do it in a completely separate DLL.
And yes, we are still talking about using the lowest common denominator, without introducing any concept more complex than a class and the if statement. More advance solution would be a DSL, in which the deployment unit would be the individual script, instead of a full DLL.
But even so, I hope that I am demonstrating the concept.
All we have to do is to stop thinking about the code as set in stone and accept that this is one of the richer way we have to express semantics.
More posts in "JFHCI" series:
- (27 Aug 2008) Quote of the Day
- (22 Aug 2008) Considering Scale
- (22 Aug 2008) The evil that is configuration
Comments
So are you suggesting a daily push to production for something like free_product_offer_of_the_day?
I completely agree with the "hard code everything" idea. It is always the case that I say, "just hard code it" to be quickly followed up with "Well, what if the customer wants to change the value? Do we want them to have to recompile the application? They don't even have Visual Studio!"
Oh, for god's sake...first off, designing for "what-if" scenarios is a textboox breaking of YAGNI. Designing for this is introducing complexity that is just there to satisfy a "best practice" that never should have become a best practice to begin with.
And, like you said, someone without the ability to compile the application should not be changing these values because 99% of the time they will not understand the implications. The only way they could understand all the implications is if they are familiar with the workings of the code...
These kinds of things should be kept distinct from user input which can affect the system. For example, if your application should allow a certain class of user to change the sales tax rate (or something similar) part of the actual domain requirements, then by all means, they need a GUI to do it! However, the user has the responsibility to know all the implications of what they are doing there...unlike all the other "magic values" which you are talking about.
Well this may work if you maintain an inhouse system for one business. But many systems out there is actually intended to be used by more than one corporation and business rules like this then MUST be user defined, be it with a DSL, admin screen, rule engine or whatever.
The system we are working on has many hundreds of companies using it. We've got "admin screens" to cover this need.
A/nders
There is a big difference between users randomly changing configuration settings, versus a business requirement that certain settings are user configurable - in which case it is your responsibility to also write full user administration systems to allow the to change these values without them having to understand what the numbers actually mean.
I second on Casey's post.
Jarda
When you're making software that will be used by more than one customer, you can't hardcode these things in.
I think you can hardcode some things in, and other things you cannot. It seems to me that part of why we are paid is to be able to differentiate between what we need to hardcode for the domain and what we need to let the user change, be it multiple customers or not. If this were a simple thing to decide then we all may be out of jobs.
Casey,
There are some operational settings that you want to expose.
Connection string, smtp, etc.
But stuff like the discount amount for a certain business rule? You can't expose it in any meaningful way
"But stuff like the discount amount for a certain business rule?"
Again, why not? Why can't Company A use the same software as Company B and A wants to give 30% discount when amount is over $10K whereas B wants to give 20% when it's over $15K?
Why is that so hard to expose? It's just a matter a validation from the admin UI.
"the system administrator has no idea what are the implications of changing such a configuration"
Why not? Given an admin screen that has a textbox for "discount percentage to be applied for preferred members" - I think that the administrator would know exactly what the implications of changing the values are.
I agree that business rules should not be changed by users without going through a full test/qa cycle, but to apply that to parameters for business rules is just being silly.
Do you go through a full test/qa cycle every time a customer does a new unique transaction within your system? I assume not. I assume your system was designed and tested to handle many data scenarios that fall within some accepted boundaries, without explicitly testing every possible permutation.
When I buy a book from Amazon, I know that there is no way that Amazon never tested for my unique transaction with the specific values for my transaction. But I stll trust that they tested for scenarios where the parameters fall within the same boundaries.
"But stuff like the discount amount for a certain business rule? You can't expose it in any meaningful way "
Ayende - Can you clairfy this more? I've done my share of work in financial industries where we can certainly expose it in a meaningful way. I'm wondering if I'm just misunderstanding you.
Much as admire Ayende for his superior tech skills, this must be one of the stupidest ideas I have heard from agile folks in a while.
Sometimes, I really feel we are going overboard with this agile thing. We exist to facilitate business. Not the other way round.
I suppose that like anything in our world the right answer is it depends.
If I was building apps that run my business I could see the need, but even then the person using the system should have a far better understanding of the business implications of changing the discount percentage from 5 to 6 than I would. If there are technical implications then I have probably not done my job very well.
I live in the world where we make 1 system that goes to many companies all with very different business rules.
Here's an example:
I have a Job that runs and looks at a history table to see if a user has changed their password. If they have it hands the event off to an IProcessor for processing.
In one scenario the system should generate an email to send to the customer for notification (EmailProcessor) at another company it should send a notification to an external system (SystemNotificationProcessor) and yet still at others it should do both (CompositeProcessor)
This is a trivial scenario for windsor to handle by means of setting up the dependencies, but I can't expect that the folks who use the system understand windsor (or binsor for that matter) configuration.
But it absolutely should be something that needs to be configurable.
If we say that configuration is done through a config file then they need to call a support line to get that change made (and we now have to worry somewhat about deployment issues with their next upgrade) or we can build a gui and let a user select from a series of checkboxes the behaviours they want. And let me tell you the day I can stop building those boring a$$ screens I will go run merrily through a field of daisies, but I just can't see how to get there from here.
Chris,
Create an on_[business event name].dsl which will contains the steps that you want to happen.
send_email
notify_system
etc.
Text is a really good way of representing those things
So I write my dsl, and tell my customer to here edit this text file?
How do I tell them what the possible options are? Intellisense?
This is a web app, and my desire to build intellisense into a javascript rich text editor is very low.
It might be a good excuse to try out silverlight but even then it seems a large task.
Or I put express or #Develop on the server and make that the 'admin' gui?
As I understand what Oren is saying, while it is hard-coded... Technically it's not. I believe he's talking about compiling custom assemblies and dropping them in place to implement the rules.
In theory, if you had a good object model and/or API. You could hand this to a customer with a copy of Visual C# Express and they would be able to maintain the system.
BTW, I started using Visual Web Express 2008 SP1 on my laptop at home just to see what I could do with it, and now that it allows you to create web application projects and include assembly projects in your solution, it's pretty powerful. Did I mention it's free?
@DevKm
Do you think that everytime some new parameter needs to be changed, developers should write admin screens with the necessary validation code in it and deploy it. Sounds to me like this would require alot more time and effort and could only be justified if this was a frequently changing parameter. A more COST EFFECTIVE way of dealing with change is by employing a DSL or JFHCI... now who's facilitating business...?
I get what he's saying - YAGNI. You don't always have to go out and build an admin screen. Or a DSL. You can drop in new assemblies, you can do other things.
I still disagree with the notion that this stuff is hard to express. I'm waiting to hear more...
In my mind this is a pretty simple issue. If there's a user story:
"As a finance manager I need to be able to change the foo percentage so that bar total will be calculated correctly based on changing business practices."
...I implement the story. I try not to go on principle either way.
What I do spend a of time on is making sure I can provide the feature with no unpredictable side effects. I often go back to the product owner with questions and concerns. Sometimes the product owner (who is usually a very savvy person) comes to the conclusion he doesn't want the finance manage to have this control after all.
Another way yo say all this is, listen to the user, they usually know what they want and are right to want it. As developers we should steer clear of establishing general principals about what users should and should not be able to do.
This is a sound concept. I understand that as "give priority to the suggestions of people who actually work with the software". This practice is not as common as you might think, however. Many companies still follow the "your boss knows best"-principle in this regard.
Comment preview