I have a question about Service Layer - now my controllers interacts with Service Layer where I work with EF Context but sometime business logic inside Service methods can be really huge approximately 1000 lines.
For example:
class OrderService {
public async Task UpdateOrder(OrderDto dto) {
if(dto.Products.Count > 3)
{
**change order status that can take 300 lines**
}
}
}
Where can I keep that logic that I use inside if statement ?
Usually I just create private method inside that service but I'm not sure that it is a good approach. Maybe create specific class for that or something like this ?
Thank you.
This question can go more to the developer's personal point of view. Here's some techniques I use to organize my code. Just try to see if they fit your scenario and change them to your need.
Move some logic to your entities.Example: An entity should be able to know if is in a good state.
Entity.Type = Square
Entity.Edges = 3
Entity.IsValid() => False // Squares has 4 edges
You can create multiple classes that will help you add some logic to your code. In a feature/entity you can create multiple validation classes and then do something like entity.AddValidation(EdgeValidator).
If you'll have a different algorithm base on conditions you can use the Strategy Pattern which is a Behavioral patterns.
If House.FamilySize == 1 then ProcessAlgorithm = SinglePersonAlgorithm
Else ProcessAlgorithm = MultiplePersonAlgorithm
ProcessAlgorithm(House)
The old and classic split a function in multiple ones.
Incapsulating different branches of if statements in separate classes may require some rework and refactoring but may well lead to great results and allow you to use patterns like for example
Chain of responsibility
Pipeline processing
and eventually all other Behavioral patterns
Related
I have several functions that deal with database interactions. (like readModelById, updateModel, findModels, etc) that I try to use in a functional style.
In OOP, I'd create a class that takes DB-connection-parameters in the constructor, creates the database-connection and save the DB-handle in the instance. The functions then would just use the DB-handle from "this".
What's the best way in FP to deal with this? I don't want to hand around the DB handle throughout the entire application. I thought about partial application on the functions to "bake in" the handle, but that creates ugly boilerplate code, doing it one by one and handing it back.
What's the best practice/design pattern for things like this in FP?
There is a parallel to this in OOP that might suggest the right approach is to take the database resource as parameter. Consider the DB implementation in OOP using SOLID principles. Due to Interface Segregation Principle, you would end up with an interface per DB method and at least one implementation class per interface.
// C#
public interface IGetRegistrations
{
public Task<Registration[]> GetRegistrations(DateTime day);
}
public class GetRegistrationsImpl : IGetRegistrations
{
public Task<Registration[]> GetRegistrations(DateTime day)
{
...
}
private readonly DbResource _db;
public GetRegistrationsImpl(DbResource db)
{
_db = db;
}
}
Then to execute your use case, you pass in only the dependencies you need instead of the whole set of DB operations. (Assume that ISaveRegistration exists and is defined like above).
// C#
public async Task Register(
IGetRegistrations a,
ISaveRegistration b,
RegisterRequest requested
)
{
var registrations = await a.GetRegistrations(requested.Date);
// examine existing registrations and determine request is valid
// throw an exception if not?
...
return await b.SaveRegistration( ... );
}
Somewhere above where this code is called, you have to new up the implementations of these interfaces and provide them with DbResource.
var a = new GetRegistrationsImpl(db);
var b = new SaveRegistrationImpl(db);
...
return await Register(a, b, request);
Note: You could use a DI framework here to attempt to avoid some boilerplate. But I find it to be borrowing from Peter to pay Paul. You pay as much in having to learn a DI framework and how to make it behave as you do for wiring the dependencies yourself. And it is another tech new team members have to learn.
In FP, you can do the same thing by simply defining a function which takes the DB resource as a parameter. You can pass functions around directly instead of having to wrap them in classes implementing interfaces.
// F#
let getRegistrations (db: DbResource) (day: DateTime) =
...
let saveRegistration (db: DbResource) ... =
...
The use case function:
// F#
let register fGet fSave request =
async {
let! registrations = fGet request.Date
// call your business logic here
...
do! fSave ...
}
Then to call it you might do something like this:
register (getRegistrations db) (saveRegistration db) request
The partial application of db here is analogous to constructor injection. Your "losses" from passing it to multiple functions is minimal compared to the savings of not having to define interface + implementation for each DB operation.
Despite being in a functional-first language, the above is in principle the same as the OO/SOLID way... just less lines of code. To go a step further into the functional realm, you have to work on eliminating side effects in your business logic. Side effects can include: current time, random numbers, throwing exceptions, database operations, HTTP API calls, etc.
Since F# does not require you to declare side effects, I designate a border area of code where side effects should stop being used. For me, the use case level (register function above) is the last place for side effects. Any business logic lower than that, I work on pushing side effects up to the use case. It is a learning process to do that, so do not be discouraged if it seems impossible at first. Just do what you have to for now and learn as you go.
I have a post that attempts to set the right expectations on the benefits of FP and how to get them.
I'm going to add a second answer here taking an entirely different approach. I wrote about it here. This is the same approach used by MVU to isolate decisions from side effects, so it is applicable to UI (using Elmish) and backend.
This is worthwhile if you need to interleave important business logic with side effects. But not if you just need to execute a series of side effects. In that case just use a block of imperative statements, in a task (F# 6 or TaskBuilder) or async block if you need IO.
The pattern
Here are the basic parts.
Types
Model - The state of the workflow. Used to "remember" where we are in the workflow so it can be resumed after side effects.
Effect - Declarative representation of the side effects you want to perform and their required data.
Msg - Represents events that have happened. Primarily, they are the results of side effects. They will resume the workflow.
Functions
update - Makes all the decisions. It takes in its previous state (Model) and a Msg and returns an updated state and new Effects. This is a pure function which should have no side effects.
perform - Turns a declared Effect into a real side effect. For example, saving to a database. Returns a Msg with the result of the side effect.
init - Constructs an initial Model and starting Msg. Using this, a caller gets the data it needs to start the workflow without having to understand the internal details of update.
I jotted down an example for a rate-limited emailer. It includes the implementation I use on the backend to package and run this pattern, called Ump.
The logic can be tested without any instrumentation (no mocks/stubs/fakes/etc). Declare the side effects you expect, run the update function, then check that the output matches with simple equality. From the linked gist:
// example test
let expected = [SendEmail email1; ScheduleSend next]
let _, actual = Ump.test ump initArg [DueItems ([email1; email2], now)]
Assert.IsTrue(expected = actual)
The integrations can be tested by exercising perform.
This pattern takes some getting-used-to. It reminds me a bit of an Erlang actor or a state machine. But it is helpful when you really need your business logic to be correct and well-tested. It also happens to be a proper functional pattern.
I'm trying to implement simple DDD/CQRS architecture without event-sourcing for now.
Currently I need to write some code for adding a notification to a document entity (document can have multiple notifications).
I've already created a command NotificationAddCommand, ICommandService and IRepository.
Before inserting new notification through IRepository I have to query current user_id from db using NotificationAddCommand.User_name property.
I'm not sure how to do it right, because I can
Use IQuery from read-flow.
Pass user_name to domain entity and resolve user_id in the repository.
Code:
public class DocumentsCommandService : ICommandService<NotificationAddCommand>
{
private readonly IRepository<Notification, long> _notificationsRepository;
public DocumentsCommandService(
IRepository<Notification, long> notifsRepo)
{
_notificationsRepository = notifsRepo;
}
public void Handle(NotificationAddCommand command)
{
// command.user_id = Resolve(command.user_name) ??
// command.source_secret_id = Resolve(command.source_id, command.source_type) ??
foreach (var receiverId in command.Receivers)
{
var notificationEntity = _notificationsRepository.Get(0);
notificationEntity.TargetId = receiverId;
notificationEntity.Body = command.Text;
_notificationsRepository.Add(notificationEntity);
}
}
}
What if I need more complex logic before inserting? Is it ok to use IQuery or should I create additional services?
The idea of reusing your IQuery somewhat defeats the purpose of CQRS in the sense that your read-side is supposed to be optimized for pulling data for display/query purposes - meaning that it can be denormalized, distributed etc. in any way you deem necessary without being restricted by - or having implications for - the command side (a key example being that it might not be immediately consistent, while your command side obviously needs to be for integrity/validity purposes).
With that in mind, you should look to implement a contract for your write side that will resolve the necessary information for you. Driving from the consumer, that might look like this:
public DocumentsCommandService(IRepository<Notification, long> notifsRepo,
IUserIdResolver userIdResolver)
public interface IUserIdResolver
{
string ByName(string username);
}
With IUserIdResolver implemented as appropriate.
Of course, if both this and the query-side use the same low-level data access implementation (e.g. an immediately-consistent repository) that's fine - what's important is that your architecture is such that if you need to swap out where your read side gets its data for the purposes of, e.g. facilitating a slow offline process, your read and write sides are sufficiently separated that you can swap out where you're reading from without having to untangle reads from the writes.
Ultimately the most important thing is to know why you are making the architectural decisions you're making in your scenario - then you will find it much easier to make these sorts of decisions one way or another.
In a project i'm working i have similar issues. I see 3 options to solve this problem
1) What i did do is make a UserCommandRepository that has a query option. Then you would inject that repository into your service.
Since the few queries i did need were so simplistic (just returning single values) it seemed like a fine tradeoff in my case.
2) Another way of handling it is by forcing the user to just raise a command with the user_id. Then you can let him do the querying.
3) A third option is ask yourself why you need a user_id. If it's to make some relations when querying the data you could also have this handles when querying the data (or when propagating your writeDB to your readDB)
I have the need to construct a WorkflowTaskQuery with a custom workflow model date as criteria. The criteria needs to be "currentDate >= myCustomDate".
I have noticed that it is possible to add custom properties to the WorkflowTaskQuery but looking into the implementation it seems like those properties all are added as equals-criterias. (reference(4.2.x): org.alfresco.repo.workflow.activiti.ActivitiWorkflowEngine.addTaskPropertiesToQuery)
To get all active tasks and do the filtering on the returned result will not be a good approach since there will be thousands of running workflow tasks in this implementation.
The only other approach I can think of would be to subclass both WorkflowTaskQuery and ActivitiWorkflowEngine and rewrite some private methods (like createRuntimeTaskQuery) and handle my special cases on my own there. (Activiti has methods like greaterThan and so on when searching for tasks based on variables....)
If anyone have any better suggestions, please feel free to share them with me :)
We are implementing a solution that drives Activiti using the Rest interface and have successfully implemented task queries using the POST /rest/service/query/task
The body of the request contains the conditions and the operator to use in query can have the following values: "equals", "notEquals", "equalsIgnoreCase", "notEqualsIgnoreCase", "lessThan", "greaterThan", "lessThanOrEquals", "greaterThanOrEquals" and "like".
Now, with that said.....I'm not sure I understand your query.
currentData >= customDate, obviously currentDate is self explanatory, but is customDate a process instance variable or a task local variable? It may impact the format of the query.
I want to handle multiple operations on a UI Component (button ,textfield, swfs,custom objects etc)
in like scaling,skewing ,color,rotations etc etc and save them too. Earlier the actions were done
using a single tool and single mxml file but now the tool is separated into different tools.
Was wondering how i can design / use something like Toolmanager class to handle actions etc?
Also the tricky part is that some objects can have more operations defined for them .
Like 'object1' has 3 operations that can be performed on it and 'object2' has 5 operations defined on it.
We are using MVC design pattern but no frameworks as such.
What are the different design patterns that can be used to do this?
Edit:
To be more precise i want implement this in AS3 OO way.
The application is similar to drawing application which supports addition of various images,text,audio,swfs etc. One added user can perform various operations of the objects..like
adding color,scaling skewing,rotation etc etc and custom effects and after that export the drawing as PNG.Likewise some effects that are applicable to text are not applicable to images
and vice versa. and some effects can be common.
Any ideas?
Probably you could have a toolbar, tools(inheriting from a common base), and some kind of property panel, these objects are accessible from a manager class which wrappes them together and makes some variables accessible for all classes.
Probably you want a selection array or vector in the manager class and a select tool to manipulate this collection
like (in the manager)
protected var _selection:Vector.<EditableBase> = new Vector.<EditableBase>();
public function get selection() { return _selection;}
and a collection about the editbase extensions and the tools avaiable for them.
every time the selection tool updates the selection collection (probably calling a method on manager from the select tool's onMouseUp method) you can update the toolbar to display the apropriate tools for the current selection
(in manager)
protected var _ToolsByType:Object (or Dictionary) = {"EditableAudio": ["toolA", "toolB", etc]};
protected var _defaultSet:Array = ["toolA", "toolB"];
and after the selection has benn manipulated (in manager also)
public function onSelectionChangedCallback():void
{
var toolsToDisplay:Array = _defaultSet;
if(_selection.length == 1)
{
//not actual syntax
var type:String = getQualifiedClassName(_selection[0]);
if(type in _ToolsByType) toolsToDisplay = _ToolsByType[type];
}
myToolBar.showSet(toolsToDisplay);
}
the ancestor for the tools should look something like this:
public class ToolBase
{
protected var _manager:ToolManager;
function ToolBase(manager:ToolManager)//and probably a bunch of other params as well
{
_manager = manager;
}
function onSelect()
{
//you can manipulate the properties panel here
}
function onDeSelect()...
function onMouseDown(mouseData:event/whateverWrapperYouHaveCreated)...
function onMouseMove...
function onMouseUp...
}
and so and so on :)
kinda straight forward.
check photoshop plugin tutorials, or google around "extending {any adobe stuff here, like flash or something}
thats javascript but the concept can be applied here as well
maybe you could use the Strategy Design Pattern by creating some extra classes in your MVC implementation
http://en.wikipedia.org/wiki/Strategy_pattern
algo, check this tool for images:
http://www.senocular.com/demo/TransformToolAS3/TransformTool.html
bye! :)
I've been doing some reading recently and have encountered the Law of Demeter. Now some of what I've read makes perfect sense e.g. the paperboy should never be able to rifle through a customers pocket, grab the wallet and take the money out. The wallet is something the customer should have control of, not the paperboy.
What throws me about the law, maybe I'm just misunderstanding the whole thing, is that stringing properties together with a heirarchy of functionality/information can be so useful. e.g. .NETs HTTPContext class.
Wouldn't code such as :
If DataTable.Columns.Count >= 0 Then
DataTable.Columns(0).Caption = "Something"
End If
Or
Dim strUserPlatform as string = HttpContext.Current.Request.Browser.Platform.ToString()
Or
If NewTerm.StartDate >= NewTerm.AcademicYear.StartDate And
NewTerm.EndDate <= NewTerm.AcademicYear.EndDate Then
' Valid, subject to further tests.
Else
' Not valid.
End If
be breaking this law? I thought (perhaps mistakenly) the point of OOP was in part to provide access to related classes in a nice heirarchical structure.
I like, for example, the idea of referencing a utility toolkit that can be used by page classes to avoid repetitive tasks, such as sending emails and encapsulating useful string methods:
Dim strUserInput As String = "London, Paris, New York"
For Each strSearchTerm In Tools.StringManipulation.GetListOfString(strUserInput, ",")
Dim ThisItem As New SearchTerm
ThisItem.Text = strSearchTerm
Next
Any clarity would be great...at the moment I can't reconcile how the law seems to banish stringing properties and methods together...it seems strange to me that so much power should be disregarded? I'm pretty new to OOP as some of you might have guessed, so please go easy :)
What the Law of Demeter (also "Law of Demeter for Functions/Methods") wants to reduce with saying "only use one dot" is that in a method you shouldn't have to assume such a lot of context from the provided arguments. This increases the dependency of the class and makes it less testable.
It doesn't mean that you can't use all of the above examples but it suggests that instead of giving your method the customer which then accesses the wallet and retrieves the money from it:
function getPayment(Customer customer)
{
Money payment = customer.leftpocket.getWallet().getPayment(100);
...
// do stuff with the payment
}
that you instead only pass what the paperboy needs to the method and as such reduce the dependency for the method if it's possible:
function getPayment(Money money)
{
// do stuff with the payment
}
Your benefit from it will be that you dont depend on the customer to have the wallet in the left pocket but instead just process the money the customer gives you. It's a decision you have to base on your individual case though. Less dependencies allow you to test easier.
I think applying the Law of Demeter to individual classes is taking it a bit too far. I think a better application is to apply it to layers in your code. For example, your business logic layer shouldn't need to access anything about the HTTP context, and your data access layer shouldn't need to access anything in the presentation layer.
Yes, it's usually good practice to design the interface of your object so that you don't have to do tons of property chaining, but imagine the hideously complex interface you'd have if you tried to do that to the DataTable and HttpContext classes you gave as examples.
The law doesn't say that you shouldn't have access to any information at all in a class, but that you should only have access to information in a way that you can't easily misuse it.
You can for example not add columns in a data table by assigning anything to the Count property:
DataTable.Columns.Count = 42;
Instead you use the Add method of the Columns object that lets you add a column in a way that all the needed information about the column is there, and also so that the data table get set up with data for that column.