Although I'm not sure if I've chosen the right name for it, anyone who's worked on a large project with lots of features has probably seen it: some boolean return function gets bloated with the interaction of every little feature. Eventually what was once a simple one or two variable check becomes:
public boolean showFavoritesTool(UserData userData){
if(currentPage.isPremiumPage())
{
return true;
}
if(!userData.isLoggedIn())
{
return false;
}
if(userData.isMember())
{
return userData.getPreferences().isFavoritesTurnedOn();
}
if(getUrlParams()["showFavorites"])
{
return getUrlParams()["showFavorites"]
}
return false;
}
Edit: Let me clarify, this is just an early example of functions like this. At some point, it would grow as new features are developed to at least twice this size. The function I was looking at that prompted this question had at least 15 variables, some of which were nested. This code may look simple, but it won't remain so as new variables are added.
Everytime a new feature is added, another entry is thrown into the flag function. They don't usually overlap, but when they do you can be sure that no one has thought about what should happen. It doesn't take long before these functions become hard to interpret.
Is there a cleaner solution to this? Also, if that cleaner solution involves more architecture, when would one implement it? As soon as a second variable is added? Or is there some breaking point?
Your question is rather general and it is difficult to understand its scope, nevertheless I will try and provide some insight which will hopefully answer it.
Everytime a new feature is added, another entry is thrown into the flag function. They don't usually overlap, but when they do you can be sure that no one has thought about what should happen
This is a nasty side effect of poor planning and design. Code should be closed for modification, but open to extension
Design with the future in mind, as mentioned previously by Yuval Itzchakov, an interface which contains an abstract showFavouritesTool() method which is overriden by each user class depending on each classes requirements will provide greater flexibility, and adhere to the Open/Closed principle. Unfortunately, with the limited information given, it would be difficult to create an example which fits your problem.
Incidently, there will be occassions where multiple boolean expressions need checking. Why not simplify the method by using one concise statement.
For example:
public boolean showFavoritesTool(UserData userData){
return currentPage.isPremiumPage()
|| userData.isLoggedIn() && userData.isMember() && userData.getPreferences().isFavoritesTurnedOn()
|| userData.isLoggedIn() && getUrlParams()["showFavorites"];
}
I would just rewrite it in a more conscious and understandable form. This requires some care because early returns, (double) negations and the like often obscure the behavior and it is easy to introduce bugs.
public boolean showFavoritesTool(UserData userData)
{
return currentPage.isPremiumPage()
|| userData.isLoggedIn() && userData.isMember() && userData.getPreferences().isFavoritesTurnedOn()
|| userData.isLoggedIn() && getUrlParams()["showFavorites"];
}
If the logic becomes is really complex it helps introducing some intermediate variables.
public boolean showFavoritesTool(UserData userData)
{
var isPremiumPage = currentPage.isPremiumPage();
var isLoggedIn = userData.isLoggedIn();
var isMemberAndHasFavoritesTurnedOn = userData.isMember() && userData.getPreferences().isFavoritesTurnedOn();
var urlIndicatesShowFavorites = getUrlParams()["showFavorites"];
return isPremiumPage
|| isLoggedIn && isMemberAndHasFavoritesTurnedOn
|| isLoggedIn && urlIndicatesShowFavorites;
}
In this example it is a bit to much but you get the idea. It is usually a good idea to align the meaning of intermediate variables with business or technical requirements.
If all the validations stay in the same place, are clear (for example, take the ! out of the second if and make it a return true, put the return value in the third if and make it a return true also, same with the last if) and commented when "favorites tool" should be shown, I don't see a problem with it.
I think your question is a bit too general, since i don't fully understand the scope of the problem. there are multiple uses of fields which we have no knowledge about.
But in general, if you are trying to categories which set of features you want to expose to a group of users, you could make them all inherit a base type, which has an abstract method with a function called SetFavoriteTool, like so:
public abstract class BaseData
{
public abstract bool ShowFavoriteTool();
}
public class UserData : BaseData
{
public override bool ShowFavoriteTool()
{
if ....
}
}
or if you're more into interfaces, you could depend on an IFavoriteTool:
public interface IFavoriteTool
{
bool ShowFavoriteTool();
}
public class UserData : IFavoriteTool
{
public bool ShowFavoriteTool()
{
if..
}
}
and then you could change your method to:
public bool ShowFavoriteTool(UserData userData)
{
var favoriteTool = (IFavoriteTool) userData;
return favoriteTool.ShowFavoriteTool();
}
This is just a lead since i don't really understand the Domain problem you're dealing with.
Hope this helps.
This is what's known as "code rot." It's a process of source degrading in performance and/or maintainability. Eventually it may degrade to a point where the performance gets so bad or it becomes so unmaintainable that you have to start over (version 2.0)
Code rod occurs as a result of incremental enhancements or bug fixes that causes your design veer further and further away from the original design.
To combat code rot, you need to have (and enforce) good standards. Have code reviews, code audits, document source, write unit tests, etc.
I will occasionally create my own enum to declare the state of the object. In this case, something similar to this:
public enum FavoriteToolState {
IsVisible,
IsHidden
}
This way, you could set the state of the favorite inside the inner methods which actually determine whether or not the favorite is premium, or whether the user has logged in, or any of those other options, and instead of checking each of those methods, you could check to see if the current FavoriteToolState is FavoriteToolState.IsVisible.
Whether or not this is cleaner could be argued either way, I suppose. I prefer this way in some cases.
Related
I have a method which should be executed if a boolean is true.
The normal way to achieve this would be:
private void OneMethod() {
if (ShouldExecute)
OtherMethod();
}
private void OtherMethod() {
Do Stuff...
}
Note that the varibale "ShouldExecute" is a global variable of the class.
But a colleague of mine recently started to put the if into the method itself.
So now it looks like this:
private void OneMethod() {
OtherMethod(ShouldExecute);
}
private void OtherMethod(bool shouldExecute) {
if (shouldExecute) {
Do Stuff...
}
}
He argues that the decision, whether the method should be executed, is a function of the method itself and thus should be a part of the method.
While i can see where he is coming from i still don't like his way. I think it just seems wrong and confusing.
If I see something like this:
var list = FilterList(list, otherParameter, yetAnotherParameter, shouldExecute);
I wouldn't read all of the parameters if they don't particually interest me. I would assume, that the list is somehow filtered by some parameters. Always.
But my argument "it feels wrong" is a pretty bad argument.
His way may clash with "Seperation of concerns" or the "Single responsibility principle" as well, which would be a stronger argument, but I'm not sure if that is the case.
But i really couldn't find any strong evidence for either of the two standpoints. And i don't really know what to search for, either...
So maybe someone here knows which way is more in line with the object-oriented programming paradigm.
And my goal is not to proof my colleague wrong, although i would be happy if were right, of course. :)
My goal is to find a good base on which we can create a policy for this case in our company's programming standards.
Thank you for your help.
I'll answer your concern describing a real-world case.
You go to your workplace and a policeman stops you. And you tell him:
hey agent, do I surpassed the maximum speed on this road?
That policeman would think that you're laughable, because if you were aware of your infraction, why you did it? And, anyway, he would fine your anyway!
Usually rules are defined by who's not the target of the whole rule (excepting when we talk about laws which should be fulfilled by any person in your country).
For me, a method isn't responsible of knowing if it should be executed, but it's a responsibility of the caller, because the same method should be callable by other methods and those may have other conditions to decide if some method should be called or not.
This way (the one your colleague proposes) you add a function to the call stack that basically does nothing if boolean value is false. The method should be called only if it has to be really executed to avoid a memory abuse.
About "separation of concerns" is your colleague to be in fault, as the called function shouldn't know "why" it has been called
I don't think it's sensible to have a parameter to determine whether the logic of a method is executed or not. As much as possible, a method should be considered a piece of logic that always carries out the same task (for different parameters). As suggested in Clean Code, if you have boolean parameters that significantly change the behaviour of a method, maybe it should be a different method.
As a rule of thumb, I would say that if the documentation ends up being something like "This method does X, unless parameter P takes value V, in which case it does Y" (maybe excepting null or empty values in some cases) it probably means that there should be different methods and the caller should be more explicit about what needs to be done.
From the following code it seems that OtherMethod is already following Single Responsibility Principle, i.e it is doing things for which it is meant for. But use of ShouldExecute inside OneMethod is hiding some thing from the one who calls OneMethod.
private void OneMethod()
{
if (ShouldExecute)
OtherMethod();
}
private void OtherMethod()
{
Do Stuff...
}
When a method expects some parameter the caller of that function knows that the parameter has some relevance in working of that function. So following code is more descriptive. But again if all the stuff OtherMethod is going execute only depends upon its parameter shouldExecute then why call the method itself. In such case previous code is better.
private void OneMethod()
{
OtherMethod(ShouldExecute);
}
private void OtherMethod(bool shouldExecute)
{
if (shouldExecute)
{
//Do Stuff...
}
}
Finally, this will be better, maintaining SRP as well as not hiding anything from the caller of OneMethod:
private void OneMethod(bool _bShouldExecute)
{
if (_bShouldExecute)
OtherMethod();
}
private void OtherMethod()
{
Do Stuff...
}
This is a question regarding the concept of OOP.
Let's say I'm creating a game and I have a few objects:
Field - representig some field on the map.
User - representing a player.
Item - representing an item that user can have (for example shovel)
Now I know that player can dig a field using shovel. And this action will be a method of one of those classes. Is there some rule to determine which of those classes should have this method.
The most obvious performer of this action is the player (User), so User class could have method like digField(Field field). But actually the field itself is most affected by this action, so maybe it shold be the Field class method, like dig(User performer) or dig(Item toolUsed). Or maybe the Item itself should have a child class like Tool with a method like digField(Field field).
There are lots of ways to solve this problem and I was just wondering if there is some kind of simple best practice there.
Like said in other answers, it depends on what else is happening (or can happen in the future).
For example, for digging there can be some options:
user.digField(field, tool): this way can be helpful when your user also needs to spend time, or maybe he gets tired, i.e. use this way if you want to FOCUS on the user.
field.dig(user, tool): this way can be helpful when the field itself should be focussed on, like setting the status of the field.
tool.dig(user, field): this way can be used to change e.g. the status of the tool, or the maintenance needed.
However, in most cases there are a multiple of statuses/changes need to be set. So maybe it is best to create a separate class Action like:
public class Action
{
public void DigField(User user, Location location, Tool tool)
{
user.Status = Digging;
user.Energy -= 50;
location.Status = Digging;
tool.Status = Digging;
tool.Usage++;
}
}
As you can see this function may grow as action might get more complex. So what is a good way to call separate functions in the appropriate classes, like a mix:
public class Action
{
public void DigField(User user, Location location, Tool tool)
{
user.DigField();
location.Dig();
tool.Dig();
}
}
public class User
{
public void DigField()
{
Status = Digging;
Energy -= 50;
}
}
public class Field
{
public void Dig()
{
Status = Digging;
}
}
public class Tool
{
public void Dig()
{
Status = Digging;
Usage++;
}
}
This has the advantage to keep the functionality where it belongs.
Nothing prevents you from passing parameters, like if the energy drain for auser depends on the type of field, use:
public class User
{
public void DigField(Field field)
{
Status = Digging;
Energy -= field.Type == Clay ? 30 : 20;
}
}
It depends on the rest of your game. You can't architect your classes without thinking about all of it. So questions such as:
Are there many tools, do they perform different actions on different objects?
Are there many types of land masses (field, stream, etc)
Does the user have any effect (such as with strength) on the action
These types of questions are useful to think about before laying out your classes. As an example, if you have many different tools, then you could tie the digging with the shovel, which will detail what it does to different types of land (and which ones it can work with). Then maybe there is a tractor, which does something different to the land.
One last thought, the closer your classes match the real world, the better the classes work as the code expands. In other words, if you were describing a shovel to someone who has never seen one, your class should model itself after that kind of description.
This not a case of overloading, I think you have recognise the complexity but you are trying to escape it. It's been you take time to model it now,it may be costly later.
Here is what I think:
User object performs the action so it must have the User.Dig() method. Maybe you can decide to pass in an Item object (eg Shovel).
Field object reacts to the action (Dig) of the User object. You now have to determine what this reaction is. Also you determine what the action is.
Like you said there are likely many approach and I think game engines have solved problems like this but I don't use them so I can't recommend. If I would have to model what explain I first try out Observable Pattern https://en.wikipedia.org/wiki/Observer_pattern?wprov=sfla1
Good luck
I have a habit of creating classes that tend to pass objects around to perform operations on them rather than assigning them to a member variable and having operations refer to the member variable. It feels much more procedural to me than OO.
Is this a terrible practice? If so, what are the adverse effects (performance, memory consumption, more error-prone)? Is it simply easier and more closely aligned to OO principles like encapsulation to favour member variables?
A contrived example of what I mean is below. I tend to do the following;
public class MyObj()
{
public MyObj() {}
public void DoVariousThings(OtherObj oo)
{
if (Validate(oo))
{
Save(oo);
}
}
private bool Validate(OtherObj oo)
{
// Do stuff related to validation
}
private bool Save(OtherObj oo)
{
// Do stuff related to saving
}
}
whereas I suspect I should be doing the following;
public class MyObj()
{
private OtherObj _oo;
public MyObj(OtherObj oo)
{
_oo = oo;
}
public void DoVariousThings()
{
if (Validate())
{
Save();
}
}
private bool Validate()
{
// Do stuff related to validation with _oo
}
private bool Save()
{
// Do stuff related to saving with _oo
}
}
If you write your programs in an object oriented language, people will expect object oriented code. As such, in your first example, they would probably expect that the reason for making oo a parameter is that you will use different objects for it all the time. In your second example, they would know that you always use the same instance (as initialized in the constructor).
Now, if you use the same object all the time, but still write your code like in your first example, you will have them thoroughly confused. When an interface is well designed, it should be obvious how to use it. This is not the case in your first example.
I think you already answered your question yourself, you seem to be aware of the fact that the 2nd approach is more favorable in general and should be used (unless there are serious reasons for the first approach).
Advantages that come to my mind immediately:
Simplified readability and maintainability, both for you and for others
Only one entry point, therefore only needing to checking for != null etc.
In case you want to put that class under test, it's way easier, i.e., getting something like this (extracting interface IOtherObj from OtherObj and working with that):
public MyObj (IOtherObj oo)
{
if (oo == null) throw...
_oo = oo;
}
Talking of the adverse effects of your way, there are none, but only if you are keeping the programs and the code to yourself,, what are you doing is NOT a standard thing, say, if after some time, you start to work making libraries and code that may be used by others also, then it is a big problem. The may pass any foo object and hope that it would work.
you have to validate the object before passing it and if the validation fails do things accordingly, but if u use the standard OOP way, there is no need for validation or taking up the cases where an inappropriate type object is pass,
In a nutshell, your way is bad for :
1. code re-usability.
2. you have to handle more exceptions.
3. okay, if u r keeping things to urself, otherwise, not a good practice.
hope, it cleared some doubt.
Today I read a book and the author wrote that in a well-designed class the only way to access attributes is through one of that class methods. Is it a widely accepted thought? Why is it so important to encapsulate the attributes? What could be the consequences of not doing it? I read somewhere earlier that this improves security or something like that. Any example in PHP or Java would be very helpful.
Is it a widely accepted thought?
In the object-oriented world, yes.
Why is it so important to encapsulate the attributes? What could be the consequences of not doing it?
Objects are intended to be cohesive entities containing data and behavior that other objects can access in a controlled way through a public interface. If an class does not encapsulate its data and behavior, it no longer has control over the data being accessed and cannot fulfill its contracts with other objects implied by the public interface.
One of the big problems with this is that if a class has to change internally, the public interface shouldn't have to change. That way it doesn't break any code and other classes can continue using it as before.
Any example in PHP or Java would be very helpful.
Here's a Java example:
public class MyClass {
// Should not be < 0
public int importantValue;
...
public void setImportantValue(int newValue) {
if (newValue < 0) {
throw new IllegalArgumentException("value cannot be < 0");
}
}
...
}
The problem here is that because I haven't encapsulated importantValue by making it private rather than public, anyone can come along and circumvent the check I put in the setter to prevent the object from having an invalid state. importantValue should never be less than 0, but the lack of encapsulation makes it impossible to prevent it from being so.
What could be the consequences of not
doing it?
The whole idea behind encapsulation is that all knowledge of anything related to the class (other than its interface) is within the class itself. For example, allowing direct access to attributes puts the onus of making sure any assignments are valid on the code doing the assigning. If the definition of what's valid changes, you have to go through and audit everything using the class to make sure they conform. Encapsulating the rule in a "setter" method means you only have to change it in one place, and any caller trying anything funny can get an exception thrown at it in return. There are lots of other things you might want to do when an attribute changes, and a setter is the place to do it.
Whether or not allowing direct access for attributes that don't have any rules to bind them (e.g., anything that fits in an integer is okay) is good practice is debatable. I suppose that using getters and setters is a good idea for the sake of consistency, i.e., you always know that you can call setFoo() to alter the foo attribute without having to look up whether or not you can do it directly. They also allow you to future-proof your class so that if you have additional code to execute, the place to put it is already there.
Personally, I think having to use getters and setters is clumsy-looking. I'd much rather write x.foo = 34 than x.setFoo(34) and look forward to the day when some language comes up with the equivalent of database triggers for members that allow you to define code that fires before, after or instead of a assignments.
Opinions on how "good OOD" is achieved are dime a dozen, and also very experienced programmers and designers tend to disagree about design choices and philosophies. This could be a flame-war starter, if you ask people across a wide varieties of language background and paradigms.
And yes, in theory are theory and practice the same, so language choice shouldn't influence high level design very much. But in practice they do, and good and bad things happen because of that.
Let me add this:
It depends. Encapsulation (in a supporting language) gives you some control over how you classes are used, so you can tell people: this is the API, and you have to use this. In other languages (e.g. python) the difference between official API and informal (subject to change) interfaces is by naming convention only (after all, we're all consenting adults here)
Encapsulation is not a security feature.
Another thought to ponder
Encapsulation with accessors also provides much better maintainability in the future. In Feanor's answer above, it works great to enforce security checks (assuming your instvar is private), but it can have much further reaching benifits.
Consider the following scenario:
1) you complete your application, and distribute it to some set of users (internal, external, whatever).
2) BigCustomerA approaches your team and wants an audit trail added to the product.
If everyone is using the accessor methods in their code, this becomes almost trivial to implement. Something like so:
MyAPI Version 1.0
public class MyClass {
private int importantValue;
...
public void setImportantValue(int newValue) {
if (newValue < 0) {
throw new IllegalArgumentException("value cannot be < 0");
}
importantValue = newValue;
}
...
}
MyAPI V1.1 (now with audit trails)
public class MyClass {
private int importantValue;
...
public void setImportantValue(int newValue) {
if (newValue < 0) {
throw new IllegalArgumentException("value cannot be < 0");
}
this.addAuditTrail("importantValue", importantValue, newValue);
importantValue = newValue;
}
...
}
Existing users of the API make no changes to their code and the new feature (audit trail) is now available.
Without encapsulation using accessors your faced with a huge migration effort.
When coding for the first time, it will seem like a lot of work. Its much faster to type: class.varName = something vs class.setVarName(something); but if everyone took the easy way out, getting paid for BigCustomerA's feature request would be a huge effort.
In Object Oriente Programming there is a principle that is known as (http://en.wikipedia.org/wiki/Open/closed_principle):
POC --> Principle of Open and Closed. This principle stays for: a well class design should be opened for extensibility (inheritance) but closed for modification of internal members (encapsulation). It means that you could not be able to modify the state of an object without taking care about it.
So, new languages only modify internal variables (fields) through properties (getters and setters methods in C++ or Java). In C# properties compile to methods in MSIL.
C#:
int _myproperty = 0;
public int MyProperty
{
get { return _myproperty; }
set { if (_someVarieble = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; } }
}
C++/Java:
int _myproperty = 0;
public void setMyProperty(int value)
{
if (value = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; }
}
public int getMyProperty()
{
return _myproperty;
}
Take theses ideas (from Head First C#):
Think about ways the fields can misused. What can go wrong if they're not set properly.
Is everything in your class public? Spend some time thinking about encapsulation.
What fields require processing or calculation? They are prime candidates.
Only make fields and methods public if you need to. If you don't have a reason to declare something public, don't.
I was thinking about object oriented design today, and I was wondering if you should avoid if statements. My thought is that in any case where you require an if statement you can simply create two objects that implement the same method. The two method implementations would simply be the two possible branches of the original if statement.
I realize that this seems extreme, but it seems as though you could try and argue it to some extent. Any thoughts on this?
EDIT
Wow that didn't take long. I suppose this is way too extreme. Is it possible to say though, that under OOP you should expect way less if statements?
SECOND EDIT
What about this: An object that determines its method implementation based on its attributes. That is to say you can implement someMethod() in two ways and specify some restrictions. At any point an object will route to the correct method implementation based on its properties. So in the case of if(x > 5) just have two methods that rely on the x attribute
I can tell you one thing. No matter what people say, thinking about simplifying and eliminating unnecessary branching is a sign of you maturing as a software developer. There are many reasons why branching is bad, testing, maintenance, higher rate of bugs and so on. This is one of the things I look for when interviewing people and is an excellent indicator how mature they are as a developer. I would encourage you to keep experimenting, simplifying your code and design by using less conditions. When I did this switch I found much less time debugging my code, it simply worked, then when I had to change something, changes were super easy to make since most of the code was sequential. Again I would encourage you 100% to keep doing what you are doing no matter what other people say. Keep in mind most developers are working and thinking at much lower level and just follow the rules. So good job bringing this up.
Explain how to implement the following without an if statement or ternary logic:
if ( x < 5 ) {
x = 0
} else {
print x;
}
Yes its true that often complex conditionals can be simplified with polymorphishm. But its not useful all the time. Go read Fowler's Refactoring book to get an idea of when.
http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html
Completely eliminating if statements is not realistic and I don't think that is what Ori is suggesting. But they can often be replaced using polymorphism. (And so can many switch statements).
Francesco Cirillo started the Anti-If Campaign to raise awareness of this issue. He says:
Knowing how to use objects lets developers eliminate IFs based on type, those that most often compromise software's flexibility and ability to evolve.
You or your team can also join the campaign.
One of my teacher used to say that. I tend to think that people being so dogmatic about that kind of thing usually don't program for a living.
Avoiding If Statement: There are many ways to do, one of them is below:
int i=0;
if(i==1)
{
//Statement1
}
if(i==2)
{
//Statement2
}
if(i==3)
{
//Statement3
}
if(i==4)
{
//Statement4
}
Using Dictionary and delegate:
delegate void GetStatement ();
Dictionary<int,GetStatement > valuesDic=new Dictionary<int,GetStatement >();
void GetStatement1()
{
//Statement1
}
void GetStatement2()
{
//Statement2
}
void GetStatement3()
{
//Statement3
}
void GetStatement4()
{
//Statement4
}
void LoadValues()
{
valuesDic.Add(1,GetStatement1);
valuesDic.Add(2,GetStatement2);
valuesDic.Add(3,GetStatement3);
valuesDic.Add(4,GetStatement4);
}
Replacing If Statement:
int i=0;
valuesDic[i].Invoke();
Have a look at the Anti-If Campaign The idea is not to replace every single if in your application with the Strategy or State Pattern. The idea is that when you have complex branching logic especially based on something like an enumeration, you should look to refactoring to the Strategy Pattern.
And that case you can remove the if all together by using a Factory. Here is a relatively straightforward example. Of course as I said in a real case, the logic in your strategies would be a bit more complex than just printing out "I'm Active".
public enum WorkflowState
{
Ready,
Active,
Complete
}
public interface IWorkflowStrategy
{
void Execute();
}
public class ActiveWorkflowStrategy:IWorkflowStrategy
{
public void Execute()
{
Console.WriteLine("The Workflow is Active");
}
}
public class ReadyWorkflowStrategy:IWorkflowStrategy
{
public void Execute()
{
Console.WriteLine("The Workflow is Ready");
}
}
public class CompleteWorkflowStrategy:IWorkflowStrategy
{
public void Execute()
{
Console.WriteLine("The Workflow is Complete");
}
}
public class WorkflowStrategyFactory
{
private static Dictionary<WorkflowState, IWorkflowStrategy> _Strategies=
new Dictionary<WorkflowState, IWorkflowStrategy>();
public WorkflowStrategyFactory()
{
_Strategies[WorkflowState.Ready]=new ReadyWorkflowStrategy();
_Strategies[WorkflowState.Active]= new ActiveWorkflowStrategy();
_Strategies[WorkflowState.Complete] = new CompleteWorkflowStrategy();
}
public IWorkflowStrategy GetStrategy(WorkflowState state)
{
return _Strategies[state];
}
}
public class Workflow
{
public Workflow(WorkflowState state)
{
CurrentState = state;
}
public WorkflowState CurrentState { get; set; }
}
public class WorkflowEngine
{
static void Main(string[] args)
{
var factory = new WorkflowStrategyFactory();
var workflows =
new List<Workflow>
{
new Workflow(WorkflowState.Active),
new Workflow(WorkflowState.Complete),
new Workflow(WorkflowState.Ready)
};
foreach (var workflow in workflows)
{
factory.GetStrategy(workflow.CurrentState).
Execute();
}
}
}
In some ways this can be a good idea. Swiching on a type field inside an object is usually a bad idea when you can use virtual functtions instead. But the virtual function mechanism is in no way intended to replace the if() test in general.
How do you decide which object's method to use without an if statement?
It depends on what the original statement is comparing. My rule of thumb is that if it's a switch or if testing equality against an enumeration, then that's a good candidate for a separate method. However, switch and if statements are used for many, many other kinds of tests -- there's no good way to replace the relational operators (<, >, <=, >=) with specialized methods, and some kinds of enumerated tests work much better with standard statements.
So you should only replace ifs if they look like this:
if (obj.Name == "foo" || obj.Name == "bar") { obj.DoSomething(); }
else if (obj.Name == "baz") { obj.DoSomethingElse(); }
else { obj.DoDefault(); }
In answer to ifTrue's question:
Well, if you have open classes and a sufficiently strong dependent type system, it's easy, if a bit silly. Informally and in no particular language:
class Nat {
def cond = {
print this;
return this;
}
}
class NatLessThan<5:Nat> { // subclass of Nat
override cond = {
return 0;
}
}
x = x.cond();
(continued...)
Or, with no open classes but assuming multiple dispatch and anonymous classes:
class MyCondFunctor {
function branch(Nat n) {
print n;
return n;
}
function branch(n:NatLessThan<5:Nat>) {
return 0;
}
}
x = new MyCondFunctor.branch(x);
Or, as before but with anonymous classes:
x = new {
function branch(Nat n) {
print n;
return n;
}
function branch(n:NatLessThan<5:Nat>) {
return 0;
}
}.branch(x);
You'd have a much easier time if you refactored that logic, of course. Remember that there exist fully Turing-complete type systems.
Assume we have conditional values.
public void testMe(int i){
if(i=1){
somevalue=value1;
}
if(i=2){
somevalue=value2;
}
if(i=3){
somevalue=value3;
}
}
//**$$$$$you can replace the boring IF blocks with Map.$$$$$**
// ============================================================
Same method would look like this:
--------------------------------
public void testMe(int i){
Map<Integer,String> map = new HashMap<Integer,String>();
map.put(1,value1);
map.put(2,value2);
map.put(3,value3);
}
This will avoid the complicated if conditions.
You can use simliar solution when using factory patterns for loading classes.
public void loadAnimalsKingdom(String animalKingdomType)
if(animalKingdomType="bird"){
Bird b = new Bird();
}
if(animalKingdomType="animal"){
Animal a= new Animal();
}
if(animalKingdomType="reptile"){
Reptile r= new Reptile();
}
}
Now using map :
public void loadAnimalsKingdom(String animalKingdomType)
{
Map <String,String> map = new HashMap<String,String>();
map.put("bird","com.animalworld.Bird.Class");
map.put("animal","com.animalworld.Animal.Class");
map.put("reptile","com.animalworld.Reptile.Class");
map.get(animalKingdomType);
***Use class loader to load the classes on demand once you extract the required class from the map.***
}
Like the solution? Give thumbs-up. - Vv
Creating a whole new class for an else, while technically doable, would likely result in code that is hard to read, maintain, or even prove correct.
That's an interesting idea. I think that you could theoretically do this, but it would be an enormous pain in a language not specifically designed to support it. I certainly don't see any reason to.
I think what he is saying or what he means to say is that he thinks it is best to avoid over-abuse of "tagging" and adding custom functionality to a class by several if statements when it better makes sense to subclass or rethink the object hierarchy.
It is quite extreme. Doing what you are suggesting would cause a lot of needless code duplication, unless the entire function was completely different, based on a single surrounding if; and if so, that if should probably have been on the other side of the method invocation.
If-statements certainly have their place in object-orient design.
Surely some form of comparison needs to be made regardless of what you do? In the end ... sure you can avoid if statements but you'd be producing code that is IDENTICAL to the code using an if statement.
Someone correct me if im wrong but I can't think of a time where you could get any win form doing this.
I think applying that argument to the idea of every if statement is pretty extreme, but some languages give you the ability to apply that idea in certain scenarios.
Here's a sample Python implementation I wrote in the past for a fixed-sized deque (double-ended queue). Instead of creating a "remove" method and having if statements inside it to see if the list is full or not, you just create two methods and reassign them to the "remove" function as needed.
The following example only lists the "remove" method, but obviously there are "append" methods and the like also.
class StaticDeque(collections.deque):
def __init__(self, maxSize):
collections.deque.__init__(self)
self._maxSize = int(maxSize)
self._setNotFull()
def _setFull(self):
self._full = True
self.remove = self._full_remove
def _setNotFull(self):
self._full = False
self.remove = self._not_full_remove
def _not_full_remove(self,value):
collections.deque.remove(self,value)
def _full_remove(self,value):
collections.deque.remove(self,value)
if len(self) != self._maxSize and self._full:
self._setNotFull()
In most cases it's not that useful of an idea, but sometimes it can be helpful.
I will say the answer is vaguely yes-ish. Especially when the language allows some heavy duty functional programming (ie C#, F#, OCaml).
A component that contains 2 if statements strongly couples two business rules so break it up.
Take that as a very general rule of thumb but I would agree. If you have a bunch of if statements, maybe you should think about another approach.
If-statements are pretty core to programming so, in short, you cannot sensibly avoid them.
However, a key goal in OOP--in fact, one of the "pillars"--is encapsulation. The old "encapsulate what varies" rule helps you remove those troublesome if and case statements where you are trying to account for every option in your object. A better solution to dealing with branches, special cases, etc. is to use something like the "Factory" design pattern (Abstract Factory or Factory Method--depending on needs, of course).
For example, rather than having your main code loop check which OS your using with if statements then branch to create GUI windows with different options for each OS, your main code would create an object from the factory, which use the OS to determine which OS-specific concrete object to make. In doing this you are taking the variations (and the long if-then-else clauses) out of your main code loop and letting the child objects handle it--so the next time you need to make a change such as supporting a new OS, you merely add a new class from the factory interface.
I've been following the anti-if talk lately and it does sound like extreme / hyperbolic rhetoric to me. However I think there is truth in this statement: often the logic of an if statement can be more appropriately implemented via polymorphism. I think it is good to keep that in mind every time you right an if statement. That being said, I think the if statement is still a core logic structure, and it should not be feared or avoided as a tenet.
My two bits here of what I understand of the Object Oriented approach -
First, what objects in a program should be intuitive. That is, I should not try to create a 'Arithmatic' class to provide mathematical functions. This is an abuse of OOD.
Second and this is a very strong opinion of mine. It should not be called Object Oriented design but Object and Method Oriented design! If the method names of the objects are themselves not intuitive then inherited objects might end up reimplementing the methods already available.
Object Oriented approach, according to me, is not a replacement for the Procedural approach. Rather it is mainly for two main reasons for the creators of the language -
Better capability of scoping of variables.
Better capability of garbage collection rather than having too many global variables.
I agree with Vance that the IF is not good, because it increases the conditional complexity and should be avoided as possible.
Polymorphism is a totally viable solution at condition it's used to make sense and not to "Avoid If".
A side note that does not fit to your OOP requirements but the Data Oriented approach also tends to avoid the branching.
You must understand what (x > 5) really mean. Assuming that x represents a number, then it basically "classifies" all numbers greater than five. So the code would look like this in a language with python syntax:
class Number(Object):
# ... Number implementation code ... #
def doSomething():
self = 0
return self
def doSomethingElse():
pass
class GreaterThan5(Number):
def doSomething():
print "I am " + self
def doSomethingElse():
print "I like turtles!"
Then we could run code like the following:
>>> type(3)
<class Number>
>>> type(3+3)
<class GreaterThan5>
>>> 3.doSomething()
0
>>> (3 + 3).doSomething()
I am 6
>>> (7 - 3).doSomethingElse()
>>>
The automatic type conversion here is important. As far as I am aware, none of the languages today allow you to mess with integers this much.
In the end, you can do in your code whatever. As long as the people reading it can understand immediately. So the polymorphic dispatch on integers or anything unordinary must have really good reasoning behind it.