I'm using elastic search with my asp.net core web api. I don't quite get where the line is drawn when it comes to repository responsibility.
Here is how I have defined my implementations:
public SearchRespository: ISearchRespository<Product>
{
private ElasticClient _client
public async Task<ISearchResponse<Product>> SearchAsync(ISearchRequest request)
{
var response = _client.SearchAsync<Product>(request);
return await products;
}
. . . // others
}
In my controller:
public SearchController : Controller
{
private ISearchRespository _repo;
public SearchController(ISearchRespository repo)
{
_repo = repo;
}
public async Task<IActionResult> Search()
{
// build my search request from Request.Query
var response = await _client.SearchAsync(request);
var model = new SearchModel
{
Products = response.Documents;
Aggregations = response.Aggregations;
}
return Ok(model)
}
As it stands the repo is passing the elastic response as is. My question is have I drawn my line right? what if I just move _client to my controller or move building request and constructing model to _repo? how do you guys get your repository right?
The fact that you use Elastic Search should be an implementation detail that especially the controller shouldn't know about, so you are absolutely right in abstracting this away from the controller. I often look at the SOLID principles to get a sense whether I'm on the right track or not. If we look at the Dependency Inversion Principle, you'll see that it guides us towards a style that is also known as Ports and Adapters, which basically means that the use of an external tool is abstracted away (the port), and on the boundary of the application you implement an Adapter that connects to that third party.
So from the sense of the Dependency Inversion Principle, you're on the right track.
There is however a lot of misunderstanding of what Martin Fowler's Repository Pattern is trying to solve. The definition is as follows:
Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
Important to note here is that a repository is intended to be used by the domain layer.
There is however a lot of misuse of the repository pattern, because many developers start to use it as a grouping structure for queries. The repository is -as I see it- not intended for all queries in the system; but only for queries that are the domain needs. These queries support the domain in making decisions for the mutations on the system.
Most queries that your system requires however are not this kind of query. Your code is a good example, since in this case you skip the domain completely and only do a read operation.
This is something that is not suited for the repository. We can verify this by comparing it with the SOLID principles again.
Let's say we have the following repository interface:
public interface IUserRepository
{
User[] FindUsersBySearchText(string searchText, bool includeInactiveUsers);
User[] GetUsersByRoles(string[] roles);
UserInfo[] GetHighUsageUsers(int reqsPerDayThreshold);
// More methods here
}
This is a typical repository abstraction that you'll see developers write. Such abstraction is problematic from perspective of the SOLID principles, because:
The Interface Segregation Principle is violated, because the interfaces are wide (have many methods) and consumers of those interfaces are forced to depend on methods that they don’t use.
The Single Responsibility Principle is violated, because the methods in the repository implementation are not highly cohesive. The only thing that relates those methods is the fact that they belong to the same concept or entity.
The design violates the Open/Closed Principle, because almost every time a query is added to the system, an existing interface and its implementations need to be changed. Every interface has at least two implementations: one real implementation and one test implementation.
A design like this also causes a lot of pain down the road, because it becomes hard to apply cross-cutting concerns (like security, auditing, logging, caching, etc) down the line.
So this is not something the Repository pattern is intended to solve; such design is just a big SOLID violation.
The solution here is to model queries separately in your system and not use a repository at all. There are many articles written about this, and you can read my take on this here.
If I look at your design, it actually has some resemblance with the design I'm promoting here, since you seem to have a generic query method that can handle many type of queries. The query message (your ISearchRequest) seems however specific to Elastic Search. This is something you should strive to prevent, as the Dependency Inversion Principle states.
I have run into a scenario that I would like to solve with Ninject but up until this point none of my work with it has cross this type of situation.
WCF Service App
W3C Log Parsing App (overly simplistic for demonstration purposes).
IW3CLogItem implemented by W3CLogItem
W3CLogItem has a public member of type IUrlData (contains the important data but can be one of 5 concrete implementations depending on what it contains).
The decision of which concrete implementation to use is based off of a string match and its constructor takes a regex pattern it will use to parse the data as well as the string to be parsed.
Currently I have a simple factory that does the string comparisons and then calls Create() to return a new concrete object (DocumentUrlItem, DriverUrlItem, AssetUrlItem, etc...).
I was looking at the wiki docs and how to name a binding, but even that only gets me half of the way.
The question I have is: Can this be done without a factory? Can I somehow place a conditional attribute on a binding (i.e. .contains, etc...) that evaluates to true to know which binding to use or am I better off sticking with the factory?
Let elaborate a bit.
If I were to write the factory without ninject in a simplified way, it would look like this:
protected IUrlData Create(string urldata)
{
if (urldata.Contains("bob"))
{
return new BobUrlData(urldata)
}
else if (urldata.Contains("tim"))
{
return new TimUrlData(urldata);
}
}
A couple of things of note:
1) The number of classes that implement IUrlData will grow over time. The strings "tim", and "bob" will be coming from a database.
2) The urldata being passed into BobUrlData and TimUrlData is not the only parameter in the real world, there will also be a regular expression (also sourced from the database which is calculated by the entries timestamp that knows how to handle that particular entry as they have evolved over time.
3) I am really curious if this can be accomplished with Ninject without the need for the factory all together, to somehow through metadata or names achieve the same work but all through bindings all while leaving the code extensible but read-only (other than the binding modules).
You are able to bind to methods with Ninject.
Ninject Wiki - Contextual Binding
You shouldn't need the factory anymore if you set up the method to return what you need. I can't say one is better than the other though since they both work, but I do prefer the factory doing the work and having that access Ninject to give me the correct implementation. Your result is still the same in the end.
Also, right above on the same page is Specifying Constraints.
from a purist point of view, an abstract factory is the correct way to abstract out the implementation from the interface of an object. with that said, ninject offers various ways of implementing what you want without using an abstract factory. The ones that I feel will help you most are ToMethod and providers
When I create classes, simple constructors tend to be the norm. On one of my current projects, a movie library, I have a Movie domain object. It has a number of properties, resulting in a constructor as follows:
public Movie(string title, int year, Genre genre, int length, IEnumerable<string> actors)
{
_title = title;
_year = year;
_genre = genre;
_length = length;
_actors = new List<string>(actors);
}
This isn't terrible, but it's not simple either. Would it be worthwhile to use a factory method (static Movie CreateMovie(...)), or a perhaps an object builder? Is there any typical pattern for instantiating domain classes?
UPDATE: thanks for the responses. I was probably overthinking the matter initially, though I've learned a few things that will be useful in more complex situations. My solution now is to have the title as the only required parameter, and the rest as named/optional parameters. This seems the all round ideal way to construct this domain object.
If you are using .NET 4.0, you can use optional/named parameters to simplify the creation of an object that accepts multiple arguments, some of which are optional. This is helpful when you want to avoid many different overloads to supply the necessary information about the object.
If you're not on .NET 4, you may want to use the Object Builder pattern to assembly your type. Object builder takes a bit of effort to implement, and keep in sync with you type - so whether there's enough value in doing so depends on your situation.
I find the builder pattern to be most effective when assembling hierarchies, rather than a type with a bunch of properties. In the latter case, I generally either overloads or optional/named parameters.
Yes, using a factory method is a typical pattern, but the question is: Why do you need it? This is what Wikipedia says about Factory Methods:
Like other creational patterns, it deals with the problem of creating objects (products) without specifying the exact class of object that will be created. The factory method design pattern handles this problem by defining a separate method for creating the objects, which subclasses can then override to specify the derived type of product that will be created.
So, the factory method pattern would make sense if you want to return subclasses of Movie. If this isn't (and won't be) a requirement, replacing the public constructor with a factory method doesn't really serve any purpose.
For the requirements stated in your question, your solution looks really fine to me: All mandatory fields are passed as parameters to the constructor. If none of your fields are mandatory, you might want to add a default initializer and use the C# object initializer syntax.
It depends.
If that is the only constructor for that class, it means all the properties are required in order to instantiate the object. If that aligns with your business rules, great. If not, it might be a little cumbersome. If, for example, you wanted to seed your system with Movies but didn't always have the Actors, you could find yourself in a pickle.
The CreateMovie() method you mention is another option, in case you have a need to separate the internal constructor from the act of creating a Movie instance.
You have many options available to your for arranging constructors. Use the ones that allow you to design your system with no smells and lots of principles (DRY, YAGNI, SRP.)
I don't see anything wrong with your constructor's interface and don't see what a static method will get you. I will have the exact same parameters, right?
The parameters don't seem optional, so there isn't a way to provide an overload with fewer or
use optional parameters.
From the point-of-view of the caller, it looks something like this:
Movie m = new Movie("Inception", 2010, Genre.Drama, 150, actors);
The purpose of a factory is to provide you a customizable concrete instance of an interface, not just call the constructor for you. The idea is that the exact class is not hard-coded at the point of construction. Is this really better?
Movie m = Movie.Create("Inception", 2010, Genre.Drama, 150, actors);
It seems pretty much the same to me. The only thing better is if Create() returned other concrete classes than Movie.
One thing to think about is how to improve this so that calling code is easy to understand. The most obvious problem to me is that it isn't obvious what the 150 means without looking at the code for Movie. There are a few ways to improve that if you wanted to:
Use a type for movie length and construct that type inline new MovieLength(150)
Use named parameters if you are using .NET 4.0
(see #Heinzi's answer) use Object Initializers
Use a fluent interface
With a fluent interface, your call would look like
Movie m = new Movie("Inception").
MadeIn(2010).
InGenre(Genre.Drama).
WithRuntimeLength(150).
WithActors(actors);
Frankly, all of this seems like overkill for your case. Named parameters are reasonable if you are using .NET 4.0, because they aren't that much more code and would improve the code at the caller.
You gave a good answer to your own question, it's the factory pattern. With the factory pattern you don't need huge constructors for encapsulation, you can set the object's members in your factory function and return that object.
This is perfectly acceptable, IMHO. I know static methods are sometimes frowned upon, but I typically drop that code into a static method that returns an instance of the class. I typically only do that for objects that are permitted to have null values.
If the values of the object can't be null, add them as parameters to the constructor so you don't get any invalid objects floating around.
I see nothing wrong with leaving the public constructor the way it is. Here are some of the rules I tend follow when deciding whether to go with a factory method.
Do use a factory method when initialization requires a complex algorithm.
Do use a factory method when initialization requires an IO bound operation.
Do use a factory method when initialization may throw an exception that cannot be guarded against at development time.
Do use a factory method when extra verbage may be warranted to enhance the readability.
So based on my own personal rules I would leave the constructor the way it is.
If you can distinguish core data members from configuration parameters, make a constructor that takes all of the core data members and nothing else (not even configuration parameters with default values—shoot for readability). Initialize the configuration parameters to sane default values (in the body of the method) and provide setters. At that point, a factory method could buy you something, if there are common configurations of your object that you want.
Better yet, if you find you have an object that takes a huge list of parameters, the object may be too fat. You have smelled the fact that your code may need to be refactored. Consider decomposing your object. The good literature on OO strongly argues for small objects (e.g. Martin Fowler, Refactoring; Bob Martin, Clean Code). Fowler explain how to decompose large objects. For example, the configuration parameters (if any) may indicate the need for more polymorphism, especially if they are booleans or enumerations (refactoring "Convert Conditional to Polymorphism").
I would need to see the way that your object is used before giving more specific advice. Fowler says that variables that are used together should be made into their own object. So, sake of illustration, if you are calculating certain things on the basis of the genre, year and length, but not the other attributes, those together may need to be broken out in to their own object—reducing the number of parameters that must be passed to your constructor.
As for me - all depending on your domain model. If your domain model allows you to create simple objects - you should do it.
But often we have a lot of composite objects and the creation of each individually is too complicated. That's why we`re looking for the best way to encapsulate the logic of composite object creation. Actually, we have only two alternatives described above - "Factory Method" and "Object Builder". Creating object through the static method looks a bit strange because we placing the object creation logic into the object. Object Builder, in turn, looks to complicated.
I think that the answer lies in the unit tests. This is exactly the case when TDD would be quite useful - we make our domain model step-by-step and understand the need of domain model complexity.
Asp.net-mvc, using nhibernate.
my vs.net layout is like:
/dao (1 class per entity for database work, using repository)
/model
/mappings
/factory (db factory that provides access to each entities Dao)
Now I need utility methods, not sure where to put them.
example:
CartItems.cs
CartIemsDao.cs
Now say I have a method like:
IList<CartItem> items = CartItemsDao.GetById(234)
Now I want to create a method that populates a Dictionary<int,CartItem> from a given IList<CartItem>. Should I create a CartItemManager.cs for this?
And what would a 'Service' type class be used for? e.g. CartService.cs
I believe someone said earlier a 'service' type class is to wrap multiple calls/logic for Dao's etc. Is that what it is?
There are several styles, you can definitely create a "helper" type that has all the static methods you need but this is not very discoverable from an API standpoint.
I would create these static methods on the data access objects themselves - this is much easier to discover. Of course nothing is stopping you from delegating the implementation of these static methods to some internal helper type.
Also as a side note: I don't personally care for the style of appending "DAO" or other similar identifiers to the names of types. The type is what it is so I would suggest that you leave off the "DAO" (but that has nothing to do with your question).
I would say that what you describe is a "Service", which I usually define loosely as [potentially] any operations I might want to make on entities that don't really fit into the entity itself (which practically by definition includes cross-aggregate operations).
To state it generally, you want transform a list of items into a dictionary of items using some function upon the item to derive the key.
With .Net generic typing, you could make a service for this so general it would fit best in a utility type of library that fits into the infrastructure layer where any other layer can utilize it.
public class CollectionToDictionaryMappingService {
IDictionary<TKey, TValue> Map<TKey, TValue>(ICollection <TValue> items, Func<TKey, TValue> keyAccessor)
{
var dictionary = new Dictionary<TKey, TValue>();
foreach (TValue val in items) {
dictionary.Add(keyAccessor(val), val);
}
return dictionary;
}
}
I propose to view it from a layered architecture point of view.
App layers
It depends how are you architecturing you app. I generally use two diferents layers for DAO and for Business/Logic.
In an information system logic layer generally replicates the methods of DAO, because the methods needed for implementing the use cases are get data / update data... much the same that the DAO layer. BUT I think it's important to separate them because you can add extra logic in the logic/business layer, things more complex (or composite) than the DAO.
List -> Dictionary case
I don't know if you need that method for business logic. If it's the case maybe the method can be private to some business class that uses it. Or it can be a public method of a protected helper class in the business layer.
If it's not the case I'd publish it in the business layer anyway.
BUT, if I follow the layered point of view... The service layer should provide methods for implementing the use cases. It is: it should provide the data structures needed. in this case: it should provide the dictionary.
So:
the convert method should be private to the business layer
or
be a generic conversion method like the proposed by qstarin
public MyClass(int someUniqueID)
{
using(//Session logic)
{
var databaseVersionOfMyClass = session.CreateCriteria(/*criteria*/)
.UniqueResult<MyClass>();
//Load logic
}
}
The code sample above is my current direction, although I've reached a point where I need a bit of a sanity check.
With NHibernate(I'm green in this area), is it common or best practice to instantiate an object from a database within the class constructor? The alternative I believe, would be to have a static method that returns the object from the database.
I've also come across a relevent question regarding constructors vs factory methods, however I don't believe this implementation fits the factory methodology.
To add an additional question onto the above, if instantiation within the constructor is the way to go, I've always used some sort of Load() method in the past. Either a specific private method that literally matches properties from the returned db object to the new class, or via a generic reflective method that assumes property names will match up. I'm curious if there is another way to "load" an object that I've missed.
I do not like this approach.
IMHO , it is better to implement some kind of repository which retrieves instances of persisted classes for you.
As an alternative, you could also follow the ActiveRecord approach, where you could have a static 'Load' method inside your class, and an instance method 'Save' for instance. (Take a look at Castle ActiveRecord).
But, for me, I prefer the Repository approach.