Say you design an API for some library.
You want to expose some data type (say Person) in the API (e.g. getAllPeople()).
Consider the following goals:
make it easy to add members to the Person (extensible)
don't introduce a dependency between the client of the library, and your implementation (coupling)
Person is likely to include internal state information that is not interesting to the client of the library
How would you go about it?
Define the Person in the library header / API package; have both the client of the library and the implementation depend on it (high coupling; very easy to extend)
Define Person in the API/header; define PersonModel extends Person in your library implementation (easy to extend; still some coupling)
Define PersonModel in the impl.; define Person extends PersonModel in the API (awful dependencies)
Define PersonModel in the impl; define Person in the API and copy the contents when needed (hard to extend; no coupling)
anything else?
In fact, Person is part of the API. It is the responsibility of the library user to choose how to decouple your API in the context of his architecture. You should not impose it.
If the user does not want to use your Person object, he has to encapsulate / copy your object.
Of course you can design Person to be extensible, but in any case it is part of the API. A user of this API is coupled to it. He has to choose when and where he needs to decouple from it and the way to do it. If Person is well designed, he might just use it everywhere. If it is poorly designed or not easy to use/extend, well he will copy the interesting part and redesign it.
When you design an API, the 'Person' kind of object should be an interface e.g. the user should not have access to the implementation. If person is an input to a service of your API, any implementation should work (Liskov principle). If Person is an output parameter, the user should get a reference, with any underlying internal implementation, there will be no coupling with the client code. It is hard when dealing with object construction, but using the *factory design patterns, you can manage even that. If there is no concrete implementation visible to the client code, you have a good API :-)
Related
I have a question about Facade design pattern. As i started learning design patterns from the book: Elements of re-useable object -oriented-software, there is a good explaination of what it is and how it solves the problem.
This Picture comes from that book:
Problem:
Suppose i add some extra functionality in the subsystem for which Domain is an Facade/interface. With this design, i think it's not possible to add extra functionality in the subsystem without changing the Domain class?
Second, suppose i use an abstract class Domain(to create a hierarchical structure) and delegate all the requests to it's subclasses so that whenever i want to add new functionality , i simply extend my new class/subsystem with Domain(abstract), would that be wrong or still i will have a Facade structure?
Same thing happends in Adapter pattern. We can have different kind of adapter and instead of hard-coding one class , can we create such an hierarchial structure without violating any OOD rule?
The facade as well as the adapter design patterns are part of the so called "wrapper" patterns (along with decorator and proxy). They essentially wrap certain functionality and provide a different interface. Their difference is on their intent:
facade: is used to provide a simple interface to clients, hiding the complexities of the operations it provides behind it
adapter: allows two incompatible interfaces to work together without changing their internal structure
decorator: allows new functionalities to be added to an object statically or dynamically without affecting the behavior of objects of the same class
proxy: a class (proxy) is used to represent and allow access to the
functionality of another class
If your components "in the back" add new functionality and you want your facade to expose this functionality, you would have to adjust your facade to do so.
If you have the Domain class (facade in your scenario) as an abstract class that others extend, you do not have a facade, you have whatever inheritance you created with your classes. Simply put there is no "wrapping" for achieving the intent of the facade pattern.
With this design, I think it's not possible to add extra functionality in the subsystem without changing the Domain class?
True. However, the changes you make may (or may not) affect the client (Process) class. If you add a new method to the Façade, it won't break the "old" clients. Although it's not its explicit intention (which is to hide complexities of a sub-system), Façade can provide a stable interface to its clients that can be extended. When I say interface, I don't mean a Java or C# interface. It's a programming interface.
A real-world example is the JOptionPane Façade in Java/Swing. Check the Java doc at the link I put and you'll see that some of its methods existed in 1.4, some in 1.6, etc. Basically, since this class is part of a Swing library, it had to remain stable so old clients of it's interface would not break. But it was still extended with new functionality by simply adding new methods.
I would say this is how Façades are typically extended, not with sub classing or hierarchy. Hierarchies are difficult to maintain, because they are brittle. If you get the abstraction wrong (the root of the hierarchy), then it affects the entire tree when you need to change it. Hierarchies make sense when the abstraction in the hierarchy is stable (certain).
The Adapter pattern has hierarchy because an Adapter adapts a method to work with several variants of a service that cannot be changed. You can see examples of several stable (abstract) services such as tax calculation, accounting services, credit authorization, etc. at https://stackoverflow.com/a/13323703/1168342.
All my entities are implementation of interfaces. Most of their properties are read-only.
My repository holds a reference to the library project where i hold all the interfaces, so technically speaking, the repository can save the aggregate root without knowing anything about it's de-facto implementation (something i believe to be a +1).
The problem here is: if most of the properties are read-only, how can I rehydrate a aggregate root without breaking OOP principles? should the repository hold a reference to the domain project and be aware of the concrete implementation of interfaces?
should the repository hold a reference to the domain project and be aware of the concrete implementation of interfaces?
As Evans describes in the Blue Book; the Repository is a role played by an implementation, to keep the application from mutating the underlying data directly. Similarly, the Aggregate Root is a role -- we don't let the application touch the actual entity, but instead just a limited part of it.
The implementation of the repository is part of the model, so it can know more about the specific entities being represented; including knowing how to extract from them a representation of state that can be handed off to your persistence component for storage.
To choose a specific context, let's pretend that we are modeling a TradeBook, and one of the interesting use cases is that of a customer placing orders.
In Java, the implementation of the Repository interface -- the bit that the application knows about, might look like
interface API.TradeBookRepository<TradeBook extends API.TradeBook> {
TradeBook getById(...);
void save(TradeBook);
}
interface API.TradeBook {
void placeOrder(...);
}
So the application knows that it has an access to a repository, but it doesn't know anything about the implementation but the promise that it
will provide something that supports placeOrder.
So the application code looks like:
API.TradeBookRepository<? extends API.TradeBook> repo = ....
API.TradeBook book = repo.getById(...);
book.placeOrder(...)
repo.save(book)
But a given repository implementation is usually coupled to a specific implementation of the book; they are paired together.
class LIFO.TradeBook implements API.TradeBook {
...
}
class LIFO.TradeBookRepository implements API.TradeBookRepository<LIFO.TradeBook> {
...
}
how can I rehydrate a aggregate root without breaking OOP principles?
To some degree, you can't. The good news is, at the boundaries, applications are not object oriented.
The thing you are putting into your durable store isn't an aggregate root; it's some representation of state. I tend to think of it as a Memento. What you really have are two functions - one converts a specific aggregate root implementation (ex: LIFO.TradeBook) to a Memento, the other converts a Memento to an aggregate root.
Key idea: you are probably going to want to change your domain model a lot more often than you are going to want to migrate the database. So the Memento needs to be designed to be stable -- in effect, the Memento is a message sent from the old domain model to the new one, so many of the lessons of message verioning apply.
Simply put, something somewhere in your application has to know about concrete implementations. If you really want to shield the repository implementation (not the contract) from knowing the concrete entities then that responsibility will simply have to fall on another collaborator (e.g. repository would delegate the rehydration to an abstract factory).
However, it's quite uncommon to have separate contracts for aggregates because you usually have a single implementation of these business concepts and there's usually no scenario where you would want to mock them in unit tests. Therefore, repository contracts and implementation are most of the time defined in terms of concrete aggregates.
What is the right way to create DTOs from business objects?
Who should be responsible for creating them? BO/DTO itself from BO/some static factory?
Where should they reside in code if I have, f.e. some core library and a specific service API library that I need DTO for? In core library next to BO(which seems incorrect)/in specific library?
If I have encapsulated fields in my BO how do DTO grab them? (obviously in case when BO is not responsible for creating DTOs)
As an example assume that I have some Person BO like this:
class Person
{
private int age;
public bool isBigEnough => age > 10;
}
I want age to be an internal state of Person but still I need to communicate my BO to some api. Or having private field in my class that I want to send somewhere already means that it should be public?
Are there any general considerations of how to use DTOs alongside business classes with encapsulated data?
___ Update:
In addition to approaches that #Alexey Groshev mentioned I came accross another one: we separate data of our BO class into some Data class with public accessors. BO wraps this data with its api(probably using composition) and when needed it can return its state as Data class as clone. So dto converter will be able to access Domain object's state but won't be able to modify it(since it will be just a copy).
There're multiple options available, but it would be difficult to recommend anything, because I don't know the details about your project/product. Anyway I'll name a few.
You can use AutoMapper to map BOs to DTOs and vise versa. I personally dislike this approach, because it's quite difficult (but possible) to keep it under control in medium/large sized projects. People don't usually bother to configure mappings properly and just expose internal state of their objects. For example, your isBigEnough would disappear and age would become public. Another potential risk is that people can map DTOs to/from EF/Hibernate objects. You can find some articles which explain why it's considered to be a bad practice.
As you suggested, a BO can create DTO by itself, but how would you implement this approach? You can add methods or factory methods to your entities, e.g. public PersonDto ToDto(). Or you can add an interface, e.g. public interface IDtoConvertable<T> { T ToDto(); }, and choose which entity or aggregate root will implement it. Your Person class would look like this class Person : IDtoConvertable<PersonDto> {... public PersonDto ToDto() {...} }. In both cases DTO namespace/assembly must to accessible by entities which sometimes can be a problem, but usually it's not a biggie. (Make sure that DTOs cannot access entities which is much worse.)
(C#) Another option is to return a delegate which creates DTO. I decided to separate it from (2), because entity doesn't really create DTO by itself, but rather exposes a functionality which creates DTO. So, you could have something like this public Func<PersonDto> ToDto() {...}. You might want to have an interface as in (2), but you get the idea, don't you? Do I like this approach? No, because it makes code unreadable.
As you see, there are more questions than answers. I'd recommend you to make a few experiments and check what works for you (your project) and what doesn't.
I think the answer to question 5 will address the other questions too.
Are there any general considerations of how to use DTOs alongside business classes with encapsulated data?
Remember, a DTO is solely to transfer data. Do not concern yourself with implementing any kind of rules in the DTO. All it is used for is to move data from one subsystem to another (NOT between classes of the same subsystem). How that data is used in the destination system is out of your control -- although as the God programmer you inherently know how it is going to be used, DO NOT let that knowledge influence your design -- and therefore there should be no assumptions expressed as behaviour or knowledge accessors -- so, no isBigEnough.
I read many topics about OOP Design Patterns of GoF, but i am not sure about "Client" concept. So what is it? How can we realize it in our application. Thank!
In the gof book, the client is the code or class that is using the classes in the pattern.
for example, from the abstract factory pattern under motivation:
Consider a user interface toolkit that supports multiple look-and-feel standards, such as Motif and Presentation Manager. Different look-and-feels define different appearances and behaviors for user interface "widgets" like scroll bars, windows, and buttons. To be portable across look-and-feel standards, an application should not hard-code its widgets for a particular look and feel. Instantiating look-and-feel-specific classes of widgets throughout the application makes it hard to change the look and feel later.
We can solve this problem by defining an abstract WidgetFactory class that declares an interface for creating each basic kind of widget. There's also an abstract class for each kind of widget, and concrete subclasses implement widgets for specific look-and-feel standards. WidgetFactory's interface has an operation that returns a new widget object for each abstract widget class. Clients call these operations to obtain widget instances, but clients aren't aware of the concrete classes they're using. Thus clients stay independent of the prevailing look and feel.
There is a concrete subclass of WidgetFactory for each look-and-feel standard. Each subclass implements the operations to create the appropriate widget for the look and feel. For example, the CreateScrollBar operation on the MotifWidgetFactory instantiates and returns a Motif scroll bar, while the corresponding operation on the PMWidgetFactory returns a scroll bar for Presentation Manager. Clients create widgets solely through the WidgetFactory interface and have no knowledge of the classes that implement widgets for a particular look and feel. In other words, clients only have to commit to an interface defined by an abstract class, not a particular concrete class.
A WidgetFactory also enforces dependencies between the concrete widget classes. A Motif scroll bar should be used with a Motif button and a Motif text editor, and that constraint is enforced automatically as a consequence of using a MotifWidgetFactory.
As a pattern, a client is an actor that initiates an interaction with a server, which is a functional, but typically passive, actor. Acting on the client's behalf as described by a request, the server performs some action and makes a report back in the form of a response.
As such, the point of a client interface is to make it convenient or possible for arbitrary code to formulate a request and attract the attention of a server. Since the request message might be conveyed over a wide variety of media (a different memory space, for example), some kind of transparent transport is usually involved, hidden behind this request interface.
That's pretty much the long and short of it as a concept. One of the drawbacks of a very flexible pattern (which certainly applies to client/server) is one needs to descend into a specific example, framework or library to speak concretely.
The client is just another module, or class, form the system use the concrete Pattern (all or part of the components construct the pattern)
A client is a caller/consumer. A client is not a subclass/implementer. In terms of a method, a client is the caller of that method. In terms of a class, a client is the caller of methods in that class.
You could say that every method has a client, because without a caller a method is dead code; however, the term client is typically reserved for the caller of a public method, since private methods are just implementation details, not relevant to design.
In a design diagram, such as a UML class diagram, a client indicates where the public access points are and how the design is used after it is implemented.
why is it recommended to define service contract as an interface.
Any specific advantages over having them as classes?
The primary goal is separate definition of your service from implementation
The user of your service should not know anything about how you implemented your service, but he should know what operations he can do and how.
That's why its using an interface instead of class, because interface doesn't contain an implementation.
You can share your interface one time and then never worry for years even if you changing implementation of its methods every day. End users will not need to recompile the code that's using your service
Of course [there are several advantages] !
The main one is probably the ability to implement multiple classes which support said Interface and to use these classes interchangeably [with regards to the particular interface]. One of the direct uses of this is with Mock classes used for testing; This is also used with IoC (Inversion of Control) pattern, and more generally wherever we care about the "What" rather than the "Who", i.e. What matters is that whichever class is in place it behaves as per the contract (the API) regardless of "who" (which class) it is.
Another salient advantage of Interfaces is the ability to modularize behavior. For example your application may implement a concept which works, say, like a List (can be iterated over, supplies a number of items, etc.) and like a widget validator (some application specific thing). By having two interfaces "describing" this particular object, you can use instances of that class wherevever you'd use a List (and just that) and similarly you can use it as a widget validator (and just that) whereever these validator are needed. This is akin to multiple inheritance but more flexible.
In a nutshell (and some other answers started with this), the Interface defines the contract and the Class(es) implement(s) it.
Technically, a single class could do both of these things, i.e. you do not __need __ to have Interfaces, but it is very preferable to define APIs for most any behavior which may be implemented by several classes (whether multiple implementations of almost the same thing as with "mock classes", or very different classes but supplying one particular generic service/feature as say two very distinct Lists.)
Because an interface IS a contract and a class is the means to fulfill a contract. There can be many different ways to fulfill a contract based on the context, so It makes more sense to have the contracts as interfaces. which can have different implementations