I'm trying to imagine how a use-case actor with multiple behaviors actually shows up in the application.
Take the following real world but oversimplified case:
An environmental consulting organization has a project manager responsible for: creating and managing clients; projects; facilities and buildings, and equipment and supplies. A lot of this is just CRUD, but there's quite a bit more.
Does it make sense to have a ProjectManager class with all the behaviors implied? Just looking at the use-case diagram, I can see 20+ methods that would be required.
Project Management Use-Case
Instead of putting all the eggs into a one basket, why don't you group responsibilities in different "roles" and then assign these roles to PM?
What I mean by that is, please bear with me and imagine:
Interface: CustomerRelations
Responsibilities: customer related ops (e.g. create customer, keep good relations with them etc)
Interface: OfficeManagement
Responsibilities: acquire necessary equipment to do business, and provide necessary supply to use them etc.
Interface: ProjectManagement
Responsibilities: monitor and supervise projects etc
And them
Class: ProjectManager implements CustomerRelations, OfficeManagement and ProjectManagement.
This way, you can easily re-shuffle responsibilities around if need be.
We can also imagine like this. Adding to answer from #Alp
A project manager has X number of responsibilities.(Customer
Relations, Office Management)
Interface: CustomerRelations Responsibilities: customer related ops (e.g. Get-feedback from customer, and other)
Interface: OfficeManagement Responsibilities:
Class: ProjectManager can have ICustomerRelations, IOfficeManagement and IProjectManagement.
Class ProjectManager
{
IOfficeManagerment officeManagement;
ICustomerRelations customerRelations;
public ProjectManager(IOfficeManagerment management, ICustomerRelations)
{
\\Inject your dependencies
}
public void GetFeedBack()
{
customerRelations.GetFeedback();
}
public void GetEquipements()
{
officeManagement.GetAvailableEquipments();
}
}
Considerations
Project-manager doesn't have to know internals how the office is
managed. He delegate the duty to some other. eg. How to get
available resources. He just want to know the available resources.
Related
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’m trying to implement domain driven design (DDD) whilst at the same time using SOLID design principles but had the following question:
If my domain entities contain only state and the behavioural methods associated with them within the ubiquitous language are placed into separate classes does this classify as either an anemic or rich domain model?
For example, instead of having this on my entity:
class Order
{
public virtual void Ship();
}
I’ve actually factored this out into a separate OO class:
class Shipper
{
public virtual void Ship(Order order);
}
From my point of view this is still inside the “model” rather than the service/application layer, therefore I believe this would still be a rich domain model.
I may however delegate the call of retrieving my order and shipping it inside the service layer as follows:
class OrderService
{
//private member construction ommitted for brevity
Repository _repository;
ShipOrder _shipper;
public void Ship(int orderId)
{
Order order = _repository.GetOrder(orderId);
_shipper.Ship(order);
}
}
The reason for NOT implementing the behavioural logic inside the domain entity is that implementing it would go against the single responsibility principle, in that the responsibility of my entity is to maintain and store state within my domain. However, my opinion on this is could be subjective.
As far as I understand, Shipper and Order are two different concepts in your domain (non-technically speaking). If that is the case, separating them is the right choice, because you should design your domain model as close to the real world as possible.
What is a shipper? Do your domain experts talk about shippers a lot? Do different shippers ship orders differently? I doubt someone working in a store would talk about a shipper. at best they would talk about the employee who ships the order.
I think separating them 'might' be fine but then shipper would be a domain service. DDD is more about lowering the communication barrier than about folling the single responsiblity principle. In DDD i doubht it would fit into your domain model for the simple reason a domain expert wouldn't talk about it. They would talking about shipping an order.
what you might do is this
class Order {
public void Ship() {
IOCContainer.Resolve<IShippingService>.ShipOrder(this);
}
}
Now you could put all the actual logic inside the shipping service (which implements the IShippingService interface). This also solves the single responsibility principle. If you read 'uncle bob's comments about the single responsiblity principle it's not so much about doing just 1 single thing, but having 1 reason to change. https://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html
If i implement my shipping logic like this i would expect this part of my code to have no reason to change at al, (since the change in the shipping process wouldn't be located here but in the ShippingService).
This way you could combine DDD and SOLID.
I'm designing a class hierarchy for a Java Project. It involves creating a class hierarchy to represent several bank accounts.
Now, all bank accounts have a few attributes in common. These can be moved to an abstract class. However, there is one attribute which is common to several of the bank accounts but not all of them. How should I implement this attribute in the class hierarchy?
I probably shouldn't implement the attribute over and over in all the relevant classes but I can't think of another way to do it..
Let me try and help you out as much as possible.
You can have an interface IBankAccount, which defines the common behavior of the Bank Accounts. There will be just method definitions. E.g. A bank account should allow credit(), debit(), getBalance() etc. methods. It can have some additional methods not so common to all Bank Accounts.
Next you can have a BaseBankAccount class that would be abstract and implement these commmon methods. This is so because credit(), debit() and getBalance() will have a common behavior across bank accounts.
Then you can define a BankDecorator interface that will define BankAccount behaviors. Special Decorators will implement this interface to add extra features to the bank accounts. E.g. CurrentBankAccountDecorator will add the Current account functionality etc.
Hope this helps.
You could use the programming concept of mixins.
See also: D. Ancona, G. Lagorio, and E. Zucca. Jam - designing a Java extension with
mixins. ACM Trans. Program. Lang. Syst., 25(5):641-712, 2003.
Q1.
In my university studies of object-oriented modelling and design they recommend thinking about what an object can do for its method, and what its responsibilities are for its attributes. All attempts at clarification have resulted in further confusion.
This tends to generate a class diagram with actors who have all the actions, and inner classes which only hold data.
This doesn't seem correct. Is there another way of thinking about how to model the objects?
Q2. Also, the course seems to emphasize modelling the objects after their real-world counterparts but it doesn't necessarily make sense in the domain model. IE. In a medical practice, they have Patient: CreateAppointment(), CancelAppointment() but that is not how it would be implemented (you would modify a the appointment collection instead). Is there another way of thinking about this?
Example Q1
Secretary: RecordAppointment(), RecordAppointmentCancellation()
Appointment: time, date,... (no methods)
Example Q2
Doctor: SeePatient()
While SeePatient is a use-case, it does not make sense for a method on the actual class. How do you think about this?
Unfortunately, the roadblock you've hit is all too typical in academia. Academic projects tend to start with video rental stores, libraries or student registration systems (yours is a variance of this with a doctor's office) and then inheritance is taught with animals. The guideline you've provided is also very typical
they recommend thinking about what an object can do for its method, and what its responsibilities are for its attributes
In fact when beginners ask I usually explain an object's property's are the things it knows about itself and its methods are the things it knows how to do. Which is really just another way of saying exactly what you have there. As you've discovered this way of thinking quickly breaks down when you start discussing more tangible systems and not just examples.
For instance the guideline works pretty well with this object:
public class Tree
{
public int Height { get; set; }
public void Grow(int byHowMuch)
{
Height += byHowMuch;
}
}
While this certainly fits the bill your right to think that it doesn't "feel" right:
public class Secretary
{
public void MakeAppoinment(Patient patient)
{
//make the appointment
}
}
So what's the solution? It's a matter of taking what you are being taught and applying it. Learning and understanding design patterns will help a lot with developing systems which are more functional than a tree that knows how to grow.
Recommended reading:
Design Patterns: Elements of Reusable Object-Oriented Software (also known as the Gang of Four or GoF)
Head First Design Patterns
Head First Object-Oriented Analysis and Design
To solve the issue you're been presented I would probably use a combination of inherited person classes and interfaces, which would perform their actions through a series of service classes. Essentially a secretary, doctor, and patient would all inherit from person and each of these classes could be passed to accompanying service classes. The service classes may or may not do things like SeePatient(). Please don't take this example to mean that person classes wouldn't have methods.
Stack Overflow has more than a few related questions which may be of use:
Is Single Responsibility Principle a rule of OOP?
Are there any rules for OOP?
why is OOP hard for me?
Additionally, it would be good to check out:
Single responsibility principle
Don't repeat yourself
PrinciplesOfOod
Finally, there isn't a single definition of what makes an application object oriented. How you apply patterns, principles etc. will define your program. The fact that you are asking yourself these questions shows that you are on the right track.
Q1
Is it possible responsibilities of your objects should be interpreted as authorization or contract requirements, as in what actions they should take? So, to take a medical example from your Q2, an object with a Scheduler role (think C#/Java interface, or Obj-C protocol) has attributes around CanEditAppointments or EditsAppointments.
Q2
From a use case perspective, a patient may be able to create an appointment, and so you might implement a Patient in your object model with a method to CreateAppointment(). But, in terms of encapsulation, you would likely instantiate an Appointment object in CreateAppointment(), and then call methods or set properties on the Appointment object to set its time, date, patient, physician, etc.
And because the Appointment collection is likely to be permanent storage like a database, it would likely be the Appointment object's responsibility to add itself to the collection (Appointment.Schedule() goes through your data access layer to save itself to the database).
That also ties back to your Q1, in that the Appointment object's responsibility is to save itself, so it might implement an ISaveAppointment interface that requires fields and methods to carry it out. It also is the Appointment's responsibility to have a date, and time, and patient, etc., before being saved, and so the ISaveAppointment interface should require they exist, and Appointment.Schedule() should validate the values are correct or have been previously validated.
You are right that in many cases there are higher order things which more naturally contain behaviour, like the system, or the user.
You can model this behaviour in classes as static methods which operate on the data model. It isn't OO, but it's fine. You can group related methods together into such classes, and soon you have the notion of "services", as in service oriented programming.
In Java there are specifications and standards for creating such classes, namely the stateless session bean in EJB. The Spring Framework has similar notions with the stereotype "Service" which can be applied to classes to tag them as being facades for business logic.
A service is then a component which encapsulates a certain functionality or behaviour in the system. It operates on a given object model (either its own internal one, or the more general business object model from the system). If you take your use cases and create services which relate directly to them, you can write very maintainable software.
The DCI Architecture is a formalisation of this and an attempt to do the same, but at the same time trying to stay true to object orientation, by adding behaviour to objects as they need it.
I still experience the confusion: "am I telling you to do something else" or "am I doing something someone else asked of me"?
Perhaps all you have to do is play Barbie's, or G.I. Joe's to understand object interaction and where responsibilities go. G.I. Joe got wounded (or Barbie broke a nail) so he calls the Dr's office. "Hey doc, this is Joe, I need an appointment." So you, the kid, tell Barbie to go to the doctor, who needs to know the doc to call and how to call - a reference and public MakeAppointment() method. The Dr. office needs to put the appointment on the books - it's own BookAppointment() method that is the office's procedure for handling appointment requests.
public abstract GenderAppropriateDolly {
protected DrOffice Drkilldare;
public override MakeAppointment() {throw new NotImplementedException();}
}
public class GIJoe : GenderAppropriateDolly {
DrKilldare = new DrOffice();
List<Appointment> myAppointments = new List<Appointment>;
public void MakeAppointment () {
myAppointments.Add(DrKilldare.BookAppointment(this));
}
}
public class DrOffice {
List<Appointment> officeAppointments = new List<Appointments>;
public Appointment BookAppointment(GenderAppropriateDolly forWhom) {
Appointment newappt = new Appointment(formWhom);
this.Appointments.Add(newappt);
return newappt;
}
}
public class Kid {
GenderAppropriateDolly myRoleModel = new GIJoe();
// Joe got wounded so ...
myRoleModel.MakeAppointment();
}
I am developing a class library which will include the object Car.
The dilemma is, Car itself will be a class with fields such as Registration Number, and other general information on the car.
But a car has an engine, chassis, etc. These objects need to be modelled too. Should they be classes embedded within Car? If not, what is the usage scenario of an embedded class?
I've learnt that composition is "part of", so you can model seperate classes and use the engine type, for example, at the field level of the car to achieve this. However, "aggregation", which is a "has a" relationship with the type being passed in the ctor, also applies (a car "has an" engine).
Which way do I go?
EDIT: I am currently on homework hence the lack of a reply from me. The class library is for a web app based around cars. I am a professional developer (I develop in .NET for a living but as a junior) so this is not a homework question.
Thanks
It really depends on your application.
For example, you could implement the wheels as separate classes, containing information about what tyre is on it, how worn it is, etc. but if your app doesn't even care about the wheels then the entire class is a waste of code.
I can see three use cases for composition:
The owning class has gotten overly complicated and should be broken down.
The owning class has multiple copies of a set of properties that could be mapped into a class. This allows you to bind all those properties together.
The contained object may need to be inspected or considered separately from the object that owns it (eg. you might want to move the Engine object to another car) or may be replaced as a single unit.
In summary: Use composition as a tool for encapsulating complexity or eliminating repetition. If it doesn't serve one of those purposes it probably isn't worth making a new class for.
A class should have as few responsibilities as possible and encapsulate and delegate other functionality to other classes. Lots of a small, simple classes that do one thing is a sign of a readable, stable codebase.
Yes, a car will "have" an engine, but I'd suggest using an interface for this and similar "has a" relationships. Again, depending on the professor, you might get bonus points for having a factory create different cars (appropriate, no?):
public class Car
{
private Engine engine;
public Car(Engine engine)
{
this.engine = engine;
}
public void accelerate()
{
this.engine.goFaster();
}
public void decelerate()
{
this.engine.goSlower();
}
}
public interface Engine
{
public void goFaster();
public void goSlower();
}
public class ReallyFastEngine implements Engine
{
public void goFaster()
{
// some code that goes really fast
}
public void goSlower()
{
// some code that goes slower
}
}
public class NotAsFastEngine implements Engine
{
public void goFaster()
{
// some code that goes not as fast
}
public void goSlower()
{
// some code that goes slower
}
}
public class CarFactory()
{
public static Car createFastCar()
{
return new Car(new ReallyFastEngine());
}
public static Car createNotAsFastCar()
{
return new Car(new NotAsFastEngine());
}
}
Seeing as it is homework, and depending on the inclinations of your tutor/professor/teacher, you are probably better to go down the route of writing a separate classes for the engine, wheels and so on. Even though it may be completely over-engineered, and your application may not care about them, it is possible that your homework will be marked by standards such as:
"Did they identify an engine class"
"Does it have sensible methods like Start()"
"Mark them down for lumping everything in one big class that is actually simpler, because they clearly don't understand composition"
Or whatever, and not the kinds of standards that the more pragmatic people in this thread apply to their own designs.
Only break down the model of the car into pieces that will be exposed as separate entities outside the scope of the car. Another way to think about it is do you really understand how your car gets started when you turn the key? As far as the typical driver is concerned, everything under the hood is one big (and noisy) black box. The auto-engineers know the common parts that need maintenance by the car owner and have explicitly designed them for a different level of user interaction, things like the oil dipstick or coolant reservoir refill cap.
Can you model each piece of the car? Sure. Is it helpful to model the individual spark plugs? Probably not.
Do you need cars with different attributes like color or size? Do you need cars with different capabilities like passenger or towing capacity? The one place that is different is if you need cars with different behaviors. This is where you really need to think about modeling a Driver object which has attributes, from simple ones like reaction-time to complex ones like aggressiveness.
Modeling vehicles as examples of object orientation or inheritance is problematic because the examples don't really explain the true distinctions between essential attributes that define a class. It's not new to StackOverflow but this question isn't a duplicate either, see this SO thread. I had this same discussion with a friend of mine and posted a log of it on my blog. Read up on the different aircraft types the FAA recognizes and how the regulations for each type are subdivided. There are lots of different types of aircraft, the biggest separation is between powered and unpowered.
Check out the definitions used by the FAA:
Aircraft means a device that is used
or intended to be used for flight in
the air.
Airplane means an engine-driven
fixed-wing aircraft heavier than air,
that is supported in flight by the
dynamic reaction of the air against
its wings.
Airship means an engine-driven
lighter-than-air aircraft that can be
steered.
There is also lighter-than-air and heavier-than-air. A hot-air balloon is unpowered and lighter-than-air. A blimp is powered and lighter-than-air. A glider is unpowered and heavier-than-air. A Boeing 757 is powered and heavier-than air but adds another category of 'fixed-wing' which is unlike a helicopter which is also powered and heavier-than-air but is 'rotary-wing'.
Here is the first four in the form of a table:
| Powered | Unpowered
---------------------------------------------------
Lighter-than-air | Blimp | Hot-air balloon
Heavier-than-air | 737 | Glider
You get the picture.
You can't just say you'll model the engine separately from the car because a car without an engine might be a whole different animal. A car without an engine is nothing like a trailer, which also doesn't have an engine but never will either. In these cases neither 'is-a' nor 'has-a' fits in the concrete way we build objects. You don't declare a blimp as being a aircraft that 'is-a' lighter-than-air, so is a hot-air balloon. The fact that they are both lighter-than-air doesn't make them related in any way except the physics they exploit. The distinction is important because the rules and regulations that apply are different. From the other angle, we don't describe a blimp as a hot-air balloon that 'has-a' engine. The aircraft aren't physically related, the relationship is how they should be handled.
If you don't need to define your objects to that level of detail, you may not need to model them to that level of detail either.
Car will be an top hierarchy object. Including simple fields like Number, ID or description.
And will have complicated fields like Engine, which is an object by itself.
So the Car will look something like:
class Car{
String ID;
Engine engine;
}
That a has-a relation.
One criteria you can have to decide whether the classes for Engine, Chasis etc.
needs to be present as an inner class (embedded class) is whether instance of
these classes can be used elsewhere in your application. In such cases the
decision is simple and it is to make these classes exist separately
(not as inner classes).
Even if these classes are not used elsewhere in your application then other
criteria can be testability. With these classes embedded inside and with your
design is it possible to have unit tests that can appropriately test your
code providing a good coverage.
For example say, if you have made an instance variable which references an
Engine object and this variable is being initialized in the Constructor of Car.And
your Engine class has some methods which needs to be tested. Then how can
you add unit tests to check the code in Engine class ? Probably you would
have some methods in Car class which expose the behavior or Engine class allowing
you to write unit tests. Then the question is if there is a need to expose
the behavior of Engine class wouldn't it be better that the Engine class
stands on it own?
Alternatively there might not be a need to explicitly test the methods in
Engine class and unit testing the methods in Car covers the Engine class code
as well. Then it reflects tight integration of Engine class with the Car class
and would mean it can remain as an inner class.
It depends on what it is you're trying to do. Trying to design a 'Car' class (or any other class for that matter) without an idea of the use cases is an exercise in futility.
You will design the classes and their relationships and interactions very differently depending on the use cases you're trying to enable.