One of the questions I was asked was that I have a database table with following columns
pid - unique identifier
orderid - varchar(20)
documentid - int
documentpath - varchar(250)
currentLocation - varchar(250)
newlocation - varchar(250)
status - varchar(15)
I have to write a c# app to move the files from currentlocation to newlocation and update status column as either 'SUCCESS' or 'FAILURE'.
This was my answer
Create a List of all the records using linq
Create a command object which would be perform moving files
using foreach, invoke a delegate to move the files -
use endinvoke to capture any exception and update the db accordingly
I was told that command pattern and delegate did not fit the bill here - i was aksed to think and implement a more favorable GoF pattern.
Not sure what they were looking for - In this day and age, do candidates keep a lot of info on head as one always has google to find any answer and come up with solution.
I sort of agree with Aaronaught's comment above. For a problem like this, sometimes you can overthink it and try to do something more than you actually need to do.
That said, the one GoF pattern that came to mind was "Iterator." In your first statement, you said you would read all the records into a List. The one thing that could be problematic with that is if you had millions of these records. You'd probably want to process them in a more successive fashion, rather than reading the entire list into memory. The Iterator pattern would give you the ability to iterate over the list without having to know the underlying (database) storage/retrieval mechanism. The underlying implementation of the iterator could retrieve one, ten, or a hundred records at a time, and dole them out to the business logic upon request. This would provide some testing benefit as well, because you could test your other "business" logic using a different type of underlying storage (e.g. in-memory list), so that your unit tests would be independent from the database.
A deep understanding of patterns is something you should definitely have as a developer - you shouldn't need to go to Google to determine which pattern to "use" because you won't have enough time to really understand that pattern between when you start reading about it and when you apply it.
Patterns are mostly about understanding forces and encapsulating variation. That is, forces create certain kinds of variation and we have well understood ways of encapsulating those kinds of variation. A "pattern" is a body of understanding about which forces lead to which kinds of variation and which methods of encapsulation best address those.
I have a friend who was teaching a course on patterns and it suddenly struck him that he could solve a given problem "using" (meaning "implementing the encapsulating technique of") every pattern in his course book. It really did a great job of helping drive home the fact that finding the right technique is more important that knowing how to apply a technique.
The Command pattern, for instance, starts with an understanding that sometimes we want to vary when something happens. In these cases, we want to decouple the decision of what to do from the decision of when to do it. In this example, I don't see any indication that when your command should be executed varies at all.
In fact, I don't really see anything that varies so there might not have been any patterns in the problem at all. If your interviewers were saying there were, then they may have some learning to do as well.
Anywho... I'd recommend Design Patterns Explained by Shalloway and Trott. You'll get a deeper understanding of what patterns are really for and how they help you do your job and, the next time they tell you that you are "using" the wrong pattern, you might just be in a position to educate them. That seems to go over pretty well for me... about 20% of the time. :)
I would rather say that the interviewer wanted you to use (or mention) the SOLID object oriented design principles here, and in that process you might use some design pattern.
For instance, we could a make a design like below which adheres to SRP, OCP, and DIP.
internal interface IStatusRecordsToMove
{
List<IRecord> Records { get; }
}
internal interface IRecord
{
string Status { get; set; }
}
internal interface IRecordsMover
{
ITargetDb TargetDb { get; }
void Move(IStatusRecordsToMove record);
}
internal interface ITargetDb
{
void SaveAndUpdateStatus(IRecord record);
}
class ProcessTableRecordsToMove : IStatusRecordsToMove
{
public List<IRecord> Records
{
get { throw new NotImplementedException(); }
}
}
internal class ProcessRecordsMoverImpl : IRecordsMover
{
#region IRecordsMover Members
public ITargetDb TargetDb
{
get { throw new NotImplementedException(); }
}
public void Move(IStatusRecordsToMove recordsToMove)
{
foreach (IRecord item in recordsToMove.Records)
{
TargetDb.SaveAndUpdateStatus(item);
}
}
#endregion
}
internal class TargetTableBDb : ITargetDb
{
public void SaveAndUpdateStatus(IRecord record)
{
try
{
//some db object, save new record
record.Status = "Success";
}
catch(ApplicationException)
{
record.Status = "Failed";
}
finally
{
//Update IRecord Status in Db
}
}
}
Related
I'm trying to specify an interface for a Folder. That interface should allow to
- Add or delete files of type IFile
- Get an List of IFile
- Broadcast events whenever a file was added/deleted/changed (e.g. for the GUI to subscribe to)
and I'm trying to find the best way to do it. So far, I came up with three ideas:
1
public interface IFolder_v1
{
ObservableCollection<IFile> files;
}
2
public interface IFolder_v2
{
void add(IFile);
void remove(IFile);
IEnumerable<IFile> files { get; }
EventHandler OnFileAdded { get; }
EventHandler OnFileRemoved { get; }
EventHandler OnFileDeleted { get; }
}
3
public interface IFolder_v3
{
void add(IFile);
void remove(IFile);
IEnumerable<IFile> files { get; }
EventHandler<CRUD_EventArgs> OnFilesChanged { get; }
}
public class CRUD_EventArgs : EventArgs
{
public enum Operations
{
added,
removed,
updated
}
private Operations _op;
public CRUD_EventArgs(Operations operation)
{
this._op = operation;
}
public Operations operation
{
get
{
return this._op;
}
}
}
Idea #1 seems really nice to implement as doesn't require much code, but has some problems: What, for example, if an implementation of IFolder only allows to add files of specific types (Say, text files), and throws an exception whenever another file is being added? I don't think that would be feasible with a simple ObservableCollection.
Idea #2 seems ok, but requires more code. Also, defining three separate events seems a bit tedious - what if an object needs to subscribe to all events? We'd need to subscribe to 3 different eventhandlers for that. Seems annoying.
Also a little less easy to use than solution #1 as now, one needs to call .Add to add files, but a list of files is stored in .files etc. - so the naming conventions are a bit less clear than having everything bundled up in one simple sub-object (.files from idea #1).
Idea #3 circumvents all of those problems, but has the longest code. Also, I have to use a custom EventArgs class, which I can't imagine is particularly clean in an interface definition? (Also seems overkill to define a class like that for simple CRUD event notifications, shouldn't there be an existing class of some sort?)
Would appreciate some feedback on what you think is the best solution (possibly even something I haven't thought of at all). Is there any best practice?
Take a look at the Framework's FileSystemWatcher class. It does pretty much what you need, but if anyway you still need to implement your own class, you can take ideas by looking at how it is implemented (which is by the way similar to your #2 approach).
Having said that, I personally think that #3 is also a very valid approach. Don't be afraid of writing long code (within reasonable limits of course) if the result is more readable and maintainable than it would be with shorter code.
Personally I would go with #2.
In #1 you just expose a entire collection of objects, allowing everyone to do anything with them.
#3 seems less self explanatory to me. Though - I like to keep thing simple when coding so I may be biased.
If watchers are going to be shorter-lived than the thing being watched, I would avoid events. The pattern exemplified by ObservableCollection, where the collection gives a subscribed observer an IDisposable object which can be used to unsubscribe is a much better approach. If you use such a pattern, you can have your class hold a weak reference (probably use a "long" weak reference) to the the subscription object, which would in turn hold a strong reference (probably a delegate) to the subscriber and to the weak reference which identifies it. Abandoned subscriptions will thus get cleaned up by the garbage collector; it will be the duty of a subscriber to ensure that a strongly-rooted reference exists to the subscription object.
Beyond the fact that abandoned subscriptions can get cleaned up, another advantage of using the
"disposable subscription-object" approach is that unsubscription can easily be made lock-free and thread-safe, and run in constant time. To dispose a subscription, simply null out the delegate contained therein. If each attempt to add a subscription causes the subscription manager to inspect a couple of subscriptions to ensure that they are still valid, the total number of subscriptions in existence will never grow to more than twice the number that were valid as of the last garbage collection.
I'm reading Vaughn Vernon's book on Implementing Domain Driven design. I have also been going through the book code, C# version, from his github here.
The Java version of the book has decorators #Transactional which I believe are from the spring framework.
public class ProductBacklogItemService
{
#Transactional
public void assignTeamMemberToTask(
string aTenantId,
string aBacklogItemId,
string aTaskId,
string aTeamMemberId)
{
BacklogItem backlogItem =
backlogItemRepository.backlogItemOfId(
new TenantId(aTenantId),
new BacklogItemId(aBacklogItemId));
Team ofTeam =
teamRepository.teamOfId(
backlogItem.tennantId(),
backlogItem.teamId());
backlogItem.assignTeamMemberToTask(
new TeamMemberId(aTeamMemberId),
ofTeam,
new TaskId(aTaskId));
}
}
What would be the equivalent manual implementation in C#? I'm thinking something along the lines of:
public class ProductBacklogItemService
{
private static object lockForAssignTeamMemberToTask = new object();
private static object lockForOtherAppService = new object();
public voice AssignTeamMemberToTask(string aTenantId,
string aBacklogItemId,
string aTaskId,
string aTeamMemberId)
{
lock(lockForAssignTeamMemberToTask)
{
// application code as before
}
}
public voice OtherAppsService(string aTenantId)
{
lock(lockForOtherAppService)
{
// some other code
}
}
}
This leaves me with the following questions:
Do we lock by application service, or by repository? i.e. Should we not be doing backlogItemRepository.lock()?
When we are reading multiple repositories as part of our application service, how do we protect dependencies between repositories during transactions (where aggregate roots reference other aggregate roots by identity) - do we need to have interconnected locks between repositories?
Are there any DDD infrastructure frameworks that handle any of this locking?
Edit
Two useful answers came in to use transactions, as I haven't selected my persistence layer I am using in-memory repositories, these are pretty raw and I wrote them (they don't have transaction support as I don't know how to add!).
I will design the system so I do not need to commit to atomic changes to more than one aggregate root at the same time, I will however need to read consistently across a number of repositories (i.e. if a BacklogItemId is referenced from multiple other aggregates, then we need to protect against race conditions should BacklogItemId be deleted).
So, can I get away with just using locks, or do I need to look at adding TransactionScope support on my in-memory repository?
TL;DR version
You need to wrap your code in a System.Transactions.TransactionScope. Be careful about multi-threading btw.
Full version
So the point of aggregates is that the define a consistency boundary. That means any changes should result in the state of the aggregate still honouring it's invariants. That's not necessarily the same as a transaction. Real transactions are a cross-cutting implementation detail, so should probably be implemented as such.
A warning about locking
Don't do locking. Try and forget any notion you have of implementing pessimistic locking. To build scalable systems you have no real choice. The very fact that data takes time to be requested and get from disk to your screen means you have eventual consistency, so you should build for that. You can't really protect against race conditions as such, you just need to account for the fact they could happen and be able to warn the "losing" user that their command failed. Often you can start finding these issues later on (seconds, minutes, hours, days, whatever your domain experts tell you the SLA is) and tell users so they can do something about it.
For example, imagine if two payroll clerks paid an employee's expenses at the same time with the bank. They would find out later on when the books were being balanced and take some compensating action to rectify the situation. You wouldn't want to scale down your payroll department to a single person working at a time in order to avoid these (rare) issues.
My implementation
Personally I use the Command Processor style, so all my Application Services are implemented as ICommandHandler<TCommand>. The CommandProcessor itself is the thing looking up the correct handler and asking it to handle the command. This means that the CommandProcessor.Process(command) method can have it's entire contents processed in a System.Transactions.TransactionScope.
Example:
public class CommandProcessor : ICommandProcessor
{
public void Process(Command command)
{
using (var transaction = new TransactionScope())
{
var handler = LookupHandler(command);
handler.Handle(command);
transaction.Complete();
}
}
}
You've not gone for this approach so to make your transactions a cross-cutting concern you're going to need to move them a level higher in the stack. This is highly-dependent on the tech you're using (ASP.NET, WCF, etc) so if you add a bit more detail there might be an obvious place to put this stuff.
Locking wouldn't allow any concurrency on those code paths.
I think you're looking for a transaction scope instead.
I don't know what persistency layer you are going to use but the standard ones like ADO.NET, Entity Framework etc. support the TransactionScope semantics:
using(var tr = new TransactionScope())
{
doStuff();
tr.Complete();
}
The transaction is committed if tr.Complete() is called. In any other case it is rolled back.
Typically, the aggregate is a unit of transactional consistency. If you need the transaction to spread across multiple aggregates, then you should probably reconsider your model.
lock(lockForAssignTeamMemberToTask)
{
// application code as before
}
This takes care of synchronization. However, you also need to revert the changes in case of any exception. So, the pattern will be something like:
lock(lockForAssignTeamMemberToTask)
{
try {
// application code as before
} catch (Exception e) {
// rollback/restore previous values
}
}
Now and again I end up with code along these lines, where I create some objects then loop through them to initialise some properties using another class...
ThingRepository thingRepos = new ThingRepository();
GizmoProcessor gizmoProcessor = new GizmoProcessor();
WidgetProcessor widgetProcessor = new WidgetProcessor();
public List<Thing> GetThings(DateTime date)
{
List<Thing> allThings = thingRepos.FetchThings();
// Loops through setting thing.Gizmo to a new Gizmo
gizmoProcessor.AddGizmosToThings(allThings);
// Loops through setting thing.Widget to a new Widget
widgetProcessor.AddWidgetsToThings(allThings);
return allThings;
}
...which just, well, feels wrong.
Is this a bad idea?
Is there a name of an anti-pattern that I'm using here?
What are the alternatives?
Edit: assume that both GizmoProcessor and WidgetProcessor have to go off and do some calculation, and get some extra data from other tables. They're not just data stored in a repository. They're creating new Gizmos and Widgets based on each Thing and assigning them to Thing's properties.
The reason this feels odd to me is that Thing isn't an autonomous object; it can't create itself and child objects. It's requiring higher-up code to create a fully finished object. I'm not sure if that's a bad thing or not!
ThingRepository is supposed to be the single access point to get collections of Thing's, or at least that's where developers will intuitively look. For that reason, it feels strange that GetThings(DateTime date) should be provided by another object. I'd rather place that method in ThingRepository itself.
The fact that the Thing's returned by GetThings(DateTime date) are different, "fatter" animals than those returned by ThingRepository.FetchThings() also feels awkward and counter-intuitive. If Gizmo and Widget are really part of the Thing entity, you should be able to access them every time you have an instance of Thing, not just for instances returned by GetThings(DateTime date).
If the Date parameter in GetThings() isn't important or could be gathered at another time, I would use calculated properties on Thing to implement on-demand access to Gizmo and Widget :
public class Thing
{
//...
public Gizmo Gizmo
{
get
{
// calculations here
}
}
public Widget Widget
{
get
{
// calculations here
}
}
}
Note that this approach is valid as long as the calculations performed are not too costly. Calculated properties with expensive processing are not recommended - see http://msdn.microsoft.com/en-us/library/bzwdh01d%28VS.71%29.aspx#cpconpropertyusageguidelinesanchor1
However, these calculations don't have to be implemented inline in the getters - they can be delegated to third-party Gizmo/Widget processors, potentially with a caching strategy, etc.
If you have complex intialization then you could use a Strategy pattern. Here is a quick overview adapted from this strategy pattern overview
Create a strategy interface to abstract the intialization
public interface IThingInitializationStrategy
{
void Initialize(Thing thing);
}
The initialization implementation that can be used by the strategy
public class GizmosInitialization
{
public void Initialize(Thing thing)
{
// Add gizmos here and other initialization
}
}
public class WidgetsInitialization
{
public void Initialize(Thing thing)
{
// Add widgets here and other initialization
}
}
And finally a service class that accepts the strategy implementation in an abstract way
internal class ThingInitalizationService
{
private readonly IThingInitializationStrategy _initStrategy;
public ThingInitalizationService(IThingInitializationStrategy initStrategy)
{
_initStrategy = initStrategy;
}
public Initialize(Thing thing)
{
_initStrategy.Initialize(thing);
}
}
You can then use the initialization strategies like so
var initializationStrategy = new GizmosInitializtion();
var initializationService = new ThingInitalizationService(initializationStrategy);
List<Thing> allThings = thingRepos.FetchThings();
allThings.Foreach ( thing => initializationService.Initialize(thing) );
Tho only real potential problem would be that you're iterating over the same loop multiple times, but if you need to hit a database to get all the gizmos and widgets then it might be more efficient to request them in batches so passing the full list to your Add... methods would make sense.
The other option would be to look into returning the gizmos and widgets with the thing in the first repository call (assuming they reside in the same repo). It might make the query more complex, but it would probably be more efficient. Unless of course you don't ALWAYS need to get gizmos and widgets when you fetch things.
To answer your questions:
Is this a bad idea?
From my experience, you rarely know if it's a good/bad idea until you need to change it.
IMO, code is either: Over-engineered, under-engineered, or unreadable
In the meantime, you do your best and stick to the best practices (KISS, single responsibility, etc)
Personally, I don't think the processor classes should be modifying the state of any Thing.
I also don't think the processor classes should be given a collection of Things to modify.
Is there a name of an anti-pattern that I'm using here?
Sorry, unable to help.
What are the alternatives?
Personally, I would write the code as such:
public List<Thing> GetThings(DateTime date)
{
List<Thing> allThings = thingRepos.FetchThings();
// Build the gizmo and widget for each thing
foreach (var thing in allThings)
{
thing.Gizmo = gizmoProcessor.BuildGizmo(thing);
thing.Widget = widgetProcessor.BuildWidget(thing);
}
return allThings;
}
My reasons being:
The code is in a class that "Gets things". So logically, I think it's acceptable for it to traverse each Thing object and initialise them.
The intention is clear: I'm initialising the properties for each Thing before returning them.
I prefer initialising any properties of Thing in a central location.
I don't think that gizmoProcessor and widgetProcessor classes should have any business with a Collection of Things
I prefer the Processors to have a method to build and return a single widget/gizmo
However, if your processor classes are building several properties at once, then only would I refactor the property initialisation to each processor.
public List<Thing> GetThings(DateTime date)
{
List<Thing> allThings = thingRepos.FetchThings();
// Build the gizmo and widget for each thing
foreach (var thing in allThings)
{
// [Edited]
// Notice a trend here: The common Initialize(Thing) interface
// Could probably be refactored into some
// super-mega-complex Composite Builder-esque class should you ever want to
gizmoProcessor.Initialize(thing);
widgetProcessor.Initialize(thing);
}
return allThings;
}
P.s.:
I personally do not care that much for (Anti)Pattern names.
While it helps to discuss a problem at a higher level of abstraction, I wouldn't commit every (anti)pattern names to memory.
When I come across a Pattern that I believe is helpful, then only do I remember it.
I'm quite lazy, and my rationale is that: Why bother remembering every pattern and anti pattern if I'm only going to use a handful?
[Edit]
Noticed an answer was already given regarding using a Strategy Service.
Recently we had a discussion regarding Data and Behavior separation in classes. The concept of separation of Data and Behaviour is implemented by placing the Domain Model and its behavior into seperate classes.
However I am not convinced of the supposed benefits of this approach. Even though it might have been coined by a "great" (I think it is Martin Fowler, though I am not sure). I present a simple example here. Suppose I have a Person class containing data for a Person and its methods (behavior).
class Person
{
string Name;
DateTime BirthDate;
//constructor
Person(string Name, DateTime BirthDate)
{
this.Name = Name;
this.BirthDate = BirthDate;
}
int GetAge()
{
return Today - BirthDate; //for illustration only
}
}
Now, separate out the behavior and data into separate classes.
class Person
{
string Name;
DateTime BirthDate;
//constructor
Person(string Name, DateTime BirthDate)
{
this.Name = Name;
this.BirthDate = BirthDate;
}
}
class PersonService
{
Person personObject;
//constructor
PersonService(string Name, DateTime BirthDate)
{
this.personObject = new Person(Name, BirthDate);
}
//overloaded constructor
PersonService(Person personObject)
{
this.personObject = personObject;
}
int GetAge()
{
return personObject.Today - personObject.BirthDate; //for illustration only
}
}
This is supposed to be beneficial and improve flexibility and provide loose coupling. I do not see how. According to me this introduces extra coding and performance penalty, that each time we have to initialize two class objects. And I see more problems in extending this code. Consider what happens when we introduce inheritance in above case. We have to inherit both the classes
class Employee: Person
{
Double Salary;
Employee(string Name, DateTime BirthDate, Double Salary): base(Name, BirthDate)
{
this.Salary = Salary;
}
}
class EmployeeService: PersonService
{
Employee employeeObject;
//constructor
EmployeeService(string Name, DateTime BirthDate, Double Salary)
{
this.employeeObject = new Employee(Name, BirthDate, Salary);
}
//overloaded constructor
EmployeeService(Employee employeeObject)
{
this.employeeObject = employeeObject;
}
}
Note that even if we segregate out the behavior in a seperate class, we still need object of the Data class for the Behaviour class methods to work on. So in the end our Behavior class contains both the data and the behavior albeit we have the data in form of a model object.
You might say that you can add some Interfaces to the mix , so we could have IPersonService and an IEmployeeService. But I think introducing interfaces for each and every class and inherting from interfaces does not seem OK.
So then can you tell me what have I achieved by seperating out the data and behavior in above case that I could not have achieved by having them in the same class ?
I agree, the separation as you implemented is cumbersome. But there are other options. What about an ageCalculator object that has method getAge(person p)? Or person.getAge(IAgeCalculator calc). Or better yet calc.getAge(IAgeble a)
There are several benefits that accrue from separating these concerns. Assuming that you intended for your implementation to return years, what if a person / baby is only 3 months old? Do you return 0? .25? Throw an exception? What if I want the age of a dog? Age in decades or hours? What if I want the age as of a certain date? What if the person is dead? What if I want to use Martian orbit for year? Or Hebrew calander?
None of that should affect classes that consume the person interface but make no use of birthdate or age. By decoupling the age calculation from the data it consumes, you get increased flexibility and increased chance of reuse. (Maybe even calculate age of cheese and person with same code!)
As usually, optimal design will vary greatly with context. It would be a rare situation, however, that performance would influence my decision in this type of problem. Other parts of the system are likely several orders of magnitude greater factors, like the speed of light between browser and server or database retrieval or serialization. time / dollars are better spent refactoring toward simplicity and maintainability than theoretical performance concerns. To that end, I find separating data and behavior of domain models to be helpful. They are, after all, separate concerns, no?
Even with such priorities, thing are muddled. Now the class that wants the persons age has another dependency, the calc class. Ideally, fewer class dependencies are desirable. Also, who is responsible instantiating calc? Do we inject it? Create a calcFactory? Or should it be a static method? How does the decision affect testability? Has the drive toward simplicity actually increased complexity?
There seems to be a disconnect between OO's instance on combining behavior with data and the single responsibility principle. When all else fails, write it both ways and then ask a coworker, "which one is simpler?"
Actually, Martin Fowler says that in the domain model, data and behavior should be combined. Take a look at AnemicDomainModel.
I realize I am about a year late on replying to this but anyway... lol
I have separated the Behaviors out before but not in the way you have shown.
It is when you have Behaviors that should have a common interface yet allow for different (unique) implementation for different objects that separating out the behaviors makes sense.
If I was making a game, for example, some behaviors available for objects might be the ability to walk, fly, jump and so forth.
By defining Interfaces such as IWalkable, IFlyable and IJumpable and then making concrete classes based on these Interfaces it gives you great flexibility and code reuse.
For IWalkable you might have...
CannotWalk : IWalkableBehavior
LimitedWalking : IWalkableBehavior
UnlimitedWalking : IWalkableBehavior
Similar pattern for IFlyableBehavior and IJumpableBehavior.
These concrete classes would implement the behavior for CannotWalk, LimitedWalking and UnlimitedWalking.
In your concrete classes for the objects (such as an enemy) you would have a local instance of these Behaviors. For example:
IWalkableBehavior _walking = new CannotWalk();
Others might use new LimitedWalking() or new UnlimitedWalking();
When the time comes to handle the behavior of an enemy, say the AI finds the player is within a certain range of the enemy (and this could be a behavior as well say IReactsToPlayerProximity) it may then naturally attempt to move the enemy closer to "engage" the enemy.
All that is needed is for the _walking.Walk(int xdist) method to be called and it will automagically be sorted out. If the object is using CannotWalk then nothing will happen because the Walk() method would be defined as simply returning and doing nothing. If using LimitedWalking the enemy may move a very short distance toward the player and if UnlimitedWalking the enemy may move right up to the player.
I might not be explaining this very clearly but basically what I mean is to look at it the opposite way. Instead of encapsulating your object (what you are calling Data here) into the Behavior class encapsulate the Behavior into the object using Interfaces and this gives you the "loose coupling" allowing you to refine the behaviors as well as easily extend each "behavioral base" (Walking, Flying, Jumping, etc) with new implementations yet your objects themselves know no difference. They just have a Walking behavior even if that behavior is defined as CannotWalk.
Funnily enough, OOP is often described as combining data and behavior.
What you're showing here is something I consider an anti-pattern: the "anemic domain model." It does suffer from all the problems you've mentioned, and should be avoided.
Different levels of an application might have a more procedural bent, which lends themselves to a service model like you've shown, but that would usually only be at the very edge of a system. And even so, that would internally be implemented by traditional object design (data + behavior). Usually, this is just a headache.
Age in intrisic to a person (any person). Therefore it should be a part of the Person object.
hasExperienceWithThe40mmRocketLauncher() is not intrinsic to a person, but perhaps to the interface MilitaryService that can either extend or aggregate the Person object. Therefore it should not be a part of the Person object.
In general, the goal is to avoid adding methods to the base object ("Person") just because it's the easiest way out, as you introduce exceptions to normal Person behavior.
Basically, if you see yourself adding stuff like "hasServedInMilitary" to your base object, you are in trouble. Next you will be doing loads of statements such as if (p.hasServedInMilitary()) blablabla. This is really logically the same as doing instanceOf() checks all the time, and indicates that Person and "Person who has seen military service" are really two different things, and should be disconnected somehow.
Taking a step back, OOP is about reducing the number of if and switch statements, and instead letting the various objects handle things as per their specific implementations of abstract methods/interfaces. Separating the Data and Behavior promotes this, but there's no reason to take it to extremes and seperate all data from all behavior.
The approach you have described is consistent with the strategy pattern. It facilitates the following design principles:
The open/closed principle
Classes should be open for extension but closed for modification
Composition over Inheritance
Behaviours are defined as separate interfaces and specific classes that implement these interfaces. This allows better decoupling between the behaviour and the class that uses the behaviour. The behaviour can be changed without breaking the classes that use it, and the classes can switch between behaviours by changing the specific implementation used without requiring any significant code changes.
The answer is really that it's good in the right situation. As a developer part of your job is to determine the best solution for the problems presented and try to position the solution to be able to accommodate future needs.
I don't do this often follow this pattern but if the compiler or environment are designed specifically to support the separation of data and behavior there are many optimizations that can be achieved in how the Platform handles and organizes your scripts.
It’s in your best interest to be familiarize yourself with as many Design Patterns as possible rather than custom building your entire solution every time and don’t be too judgmental because the pattern doesn’t immediately make sense. You can often use existing design patterns to achieve flexible and robust solutions throughout your code. Just remember they are all meant as a starting point so you should always be prepared to customize to accommodate the individual scenarios you encounter.
I've a need to add method that will calculate a weighted sum of worker salary and his superior salary. I would like something like this:
class CompanyFinanse
{
public decimal WeightedSumOfWorkerSalaryAndSuperior(Worker WorkerA, Worker Superior)
{
return WorkerA.Salary + Superior.Salary * 2;
}
}
Is this a good design or should I put this method somewhere else? I'm just staring designing project and think about a good, Object Oriented way of organize methods in classes. So I would like start from beginning with OOP on my mind. Best practice needed!
I would either put it in the worker class, or have a static function in a finance library. I don't think a Finance object really makes sense, I think it would be more of a set of business rules than anything, so it would be static.
public class Worker {
public Worker Superior {get;set;}
public readonly decimal WeightedSalary {
get {
return (Superior.Salary * 2) + (this.Salary)
}
}
public decimal Salary {get;set;}
}
or
public static class Finance {
public static decimal WeightedSumOfWorkerSalaryAndSuperior(Worker WorkerA, Worker Superior) {
return WorkerA.Salary + Superior.Salary * 2; }
}
For your design to be Object Oriented, you should start by thinking of the purpose of the entire application. If there is only one method in your application (weighted sum), then there isn't too much design to go on.
If this is a finance application, maybe you could have a Salary class which contains a worker's salary and some utility functions.
For the method you pointed out, if the Worker class has a reference to his Superior, you could make this method part of the Worker class.
Without more information on the purpose of the application, it's difficult to give good guidance.
So it may be impossible to give you a complete answer about "best practices" without knowing more about your domain, but I can tell you that you may be setting yourself up for disaster by thinking about the implementation details this early.
If you're like me then you were taught that good OOD/OOP is meticulously detailed and involves BDUF. It wasn't until later in my career that I found out this is the reason so many projects become egregiously unmaintainable later on down the road. Assumptions are made about how the project might work, instead of allowing the design to emerge naturally from how the code is actually going to be used.
Simply stated: You need to being doing BDD / TDD (Behavior/Test Driven Development).
Start with a rough domain model sketched out, but avoid too much detail.
Pick a functional area that you want to get started with. Preferably at the top of the model, or one the user will be interacting with.
Brainstorm on expected functionality that the unit should have and make a list.
Start the TDD cycle on that unit and then refactor aggressively as you go.
What you will end up with is exactly what you do need, and nothing you don't (most of the time). You gain the added benefit of having full test coverage so you can refactor later on down the road without worrying about breaking stuff :)
I know I haven't given you any code here, but that is because anything I give you will probably be wrong, and then you will be stuck with it. Only you know how the code is actually going to be used, and you should start by writing the code in that way. TDD focuses on how the code should look, and then you can fill in the implementation details as you go.
A full explanation of this is beyond the scope of this post, but there are a myriad of resources available online as well as a number of books that are excellent resources for beginning the practice of TDD. These two guys should get you off to a good start.
Martin Fowler
Kent Beck
Following up on the answer by brien, I suggest looking at the practice of CRC cards (Class-Responsibility-Collaboration). There are many sources of information, including:
this tutorial from Cal Poly,
this orientation on the Agile Modeling web site, and
The CRC Card Book, which discusses the practice and its use with multiple languages.
Understanding which class should "own" a particular behavior (and/or which classes should collaborate in implementing a given use case), is in general a top-down kind of discussion driven by the overall design of what your system is doing for its users.
It is easy to find out whether your code needs improvement. There is a code smell in your snippet. You should address that.
It is good that you have very declarative name for the method. But it is too long. It sounds like if you keep that method in this Finanse class it is inevitable that you have to use all those words in the method name to get the sense of what that method is intended to do.
It basically means that this method may not belong to this class.
One way to address this code smell is to see if you could get a shorter method name if we have the method on other class. I see you have Worker and Salary classes.
Assuming those are the only classes left and you don't want to add up more classes, I would put this on Salary. Salary knows how to calculate weighted salary given another salary (Superior salary in this case) as input. You don't need more than two words for the method name now.
#Shawn's answer is one variation of addressing this code smell. (I think you can call it as 'long method name' code smell)