I have a review table for courses which is made up of multiple objects for different courses.A student should review the courses he is enrolled in every month.The Math,Science,History are tables by themselves but I store foreign keys in the Review table so that each review for the courses is associated with the respective table.
NOTE:a student can only be enrolled in two courses
#Entity
class Review{
//multiple time fields here here
#OneToOne(cascade=CascadeType.ALL,optional=true)
#JoinColumn(name="math_review_id")
Math m;
#OneToOne(cascade=CascadeType.ALL,optional=true)
#JoinColumn(name="science_review_id")
Science s;
#OneToOne(cascade=CascadeType.ALL,optional=true)
#JoinColumn(name="history_review_id")
History h;
}
Super Class
#MappedSuperclass
class Course {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
int id;
#ManyToOne(fetch = FetchType.LAZY,
cascade = { CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.PERSIST,
CascadeType.REFRESH },
)
#JoinColumn(name = "student_id")
private Student student;
}
Subclass History
#Entity
class History extends Course{
//fields specific to history course
}
Subclass Math
#Entity
class Math extends Course{
//fields specific to math course
}
Student class
#Entity
class Student{
//fields name,id,...
#OneToMany(mappedBy = "student",
cascade = CascadeType.ALL,
fetch = FetchType.LAZY)
private List<Review> reviewsList;
}
I check what courses the student is enrolled in and initialize the Math,Science,History accordingly.I pass a Review object to my reviews.jsp and save the returned #ModelAttribute using hibernate.I dont initialize the courses the student is not enrolled in.I thought uninitialized objects wont be saved but hibernate makes null entries even if not initialized ( I think because they are mapped to a table and are inside a persistent class). I need help how to dynamically construct Review object just with the courses the student is enrolled in.My current design might have flows,any better design suggestions are much appreciated(I have minimal experience in Java and hibernate)
As a suggestion I think you should be weary of creating a class per course. Would it not be sufficient to have a Course class which has a member of type, which could be Math, Science or History. Even that type could itself be an entity: CourseType, which you could have entries for so in your code there would be no Math, Science or History. Instead those are in a database, instead of code.
The Review object would only then interact with a Course. Just think of also all the work you will need to do when you add another course. You will have to update many different files and even add a table in your database, I don't believe you should need to do that.
I imagine you may have some differences between Course classes, and it may be a bit awkward having all these in one class. But from my experience this is typically worth doing, as it drastically reduces the amount of code and allows for more courses to be added without code.
Edit I still strongly recommend you consider reevaluating your decision of 1 class per a course, but anyway your decision. It's really unclear what this Review object is. You say that there are only 2 courses a student will be enrolled in so I imagine that 2 of these fields are null, then. But then it confuses me because you have one class per course, but you have an overeaching review object across all subjects. I would have expected to see:
class EnrolementReview{
Course courseA;
Course courseB;
}
Otherwise if your review depends on fields in your Math, or Science courses, I would expect to have a review class for each course:
class MathReview {
MathCourse course;
}
Or you might have a generic base class for review
abstract class CourseReview<C extends Course> {
C course;
}
if you had common functionality between them. And then an SemesterReview class for reviewing 2 classes in a semester:
class SemesterReview{
CourseReview review1;
CourseReview review2;
}
As far as dynamic composition, IMO I don't think it makes much sense in a statically typed language this notion. You have builder patterns and cake patterns and the like. Some programming languages have some nice stuff in this area like Scala traits but the benefits are very limited, nothing you couldn't do in Java wait a couple of class casts which are a bit evil but it gets the job done.
For all the many permutations of design patterns and methods available to you as a developer, I think it's a bit easier to look at some of the outputs of your design decision, such as:
How many classes am I going to write?
Will I be able to add more courses without writing code and changing
the database tables?
Can somebody else understand my code?
Last Edit
In regards to many null field being a concern, you have some options. Either you have null fields (which you seem to not like), or you do something like encapsulate variable types as an entity (for example each course has a list of Strings, Integers, Doubles etc), which I've seen used quite a bit in many different situations. That works out ok but you do delay some areas which may have been at compile to run-time, as you may need an integer which has a variable name of scienceCategory etc. It also can be awkward if you have some structured data. In general that approach is only good if you really don't know how a client is going to use your system and so you expose more of it to them to use.
However my personal favourite, is to follow the natural composition of your class, and encapsulate families of variables into their own class, which you expect wont always be applicable, as in if one isn't applicable all the others wont be either. The logic whether these classes are present should be very explicit however, either they should be Optional<ScienceInformation> or you should have some methods somewhere which returns a boolean whether or not this option should exist or not. Then operations can be performed on those options in the system you create. Just need to be careful you don't create objects which are too deeply nested as in objects which are made up of objects, which are made up of objects, (not always a problem but usually it is).
But really I don't think it's super important what way you choose, none of them will give you the comfy feeling that writing a class gives you. Just need to think about how you are going to abstract over these entities (eg. Course) in a way which will not lead you to an un-maintainable mess. You clearly have a very complete knowledge of your domain but you should write your code in a way where I (somebody who doesn't know about how many courses are in a semester) can read the code and then find that out without reading comments (that would be cheating), what the answer to that question is.
Related
I have a situation where I have to make a choice between two options and it's not clear for me what is the difference between that options. I will be very thankful if somebody could explain to me which one should I choose and why.
Long story short I have a simple JPA entity (Kotlin language):
#Entity
#Table(name = "account")
data class AccountEntity(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long,
var balance: Int,
#ManyToOne
var accountType: AccountTypeEntity
)
And in business-logic layer I want to have a method for updating account balance by its accountId. Basically I need to load account entity by id, then set new balance and lastly use save method which is provided by Hibernate. But I also found the fact that I don't need to call save method in explicit form if my method will be annotated with #transactional. So from that point I have two options
First one
fun updateAccountBalance(id: Long, balance: Int) {
val account = accountRepository.findById(id).orElseThrow { RuntimeException("No account with id=$id found") }
account.balance = balance
accountRepository.save(account)
}
Second one
#Transactional
fun updateAccountBalance(id: Long, balance: Int) {
val account = accountRepository.findById(id).orElseThrow { RuntimeException("No account with id=$id found") }
account.balance = balance
}
Firstly, for me it's not clear what will be the difference of those options in terms of database. Could you please clarify it?
Secondly, I think that in such method I don't really need TRANSACTION (in terms of database) at all because I make only one 'write' operation and for me it looks redundant to use to avoid calling hibernate save method in explicit form. But may be I'm wrong and there are some reasons to use transaction even here. So please correct me.
The difference is almost none in this case. The first example also creates a transaction as it will be created by the save() call when there is no running transaction to adopt. It will live for as long as the save() call. In the second example you create a transaction yourself, which will basically live for just as long as the method invocation. Since there is almost no logic in these methods their footprint will be mostly identical.
This is not a great example to try and figure this out as it is too simplistic. Things will get more interesting when you perform more complicated updates to the entity which may touch multiple tables and records and the same time, especially when you start to do changes which will cause cascaded persists, updates and deletes to happen when you modify a OneToMany collection.
Imagine a system which processes orders. orders have orderlines. And orders are tied to invoices. And orderlines are tied to invoicelines. And maybe orders have parent orders because they're grouped together. And payments are split in bookings and bookinglines which are tied to the orders, orderlines, invoices and invoicelines. Imagine what such an entity hierarchy does in a single save() statement.
In such cases it is all the more clear why a function such as save() still creates a transaction; that one save() call can still represent anywhere between one and thousands of statements being executed depending on the complexity of the entity hierarchy. Having the possibility to rollback all changes in case of a failure is a must.
When you start to work with such an entity structure, you will likely gravitate to using a #Transactional setup quite quickly as you will be running into the infamous lazy initialization error sooner or later.
I'm having a hard time understanding Objectify entities relationship concepts. Let's say that i have entities User and UsersAction.
class User{
String nick;
}
class UsersAction{
Date actionDate;
}
Now in the frond-end app I want to load many UsersActions and display it, along with corresponding user's nick. I'm familiar with two concepts of dealing with this:
Use Ref<>,
I can put a #Load Ref in UsersAction, so it will create a link between this entites. Later while loading Users Action, Objectify will load proper User.
class User{
String nick;
}
class UsersAction{
#Load Ref<User> user;
Date actionDate;
}
Store Id and duplicate nick in UsersAction:
I can also store User's Id in UsersAction and duplicate User's nick while saving UsersAction.
class User{
String nick;
}
class UsersAction{
Long usersId;
String usersNick;
Date actionDate;
}
When using Ref<>, as far as I understand, Objectify will load all needed UsersActions, then all corresponding Users. When using duplication Objectify will only need to load UsersActions and all data will be there. Now, my question is. Is there a significant difference in performance, between this approaches? Efficiency is my priority but second solution seems ugly and dangerous to me since it causes data duplication and when User changes his nick, I need to update his Actions too.
You're asking whether it is better to denormalize the nickname. It's hard to say without knowing what kinds of queries you plan to run, but generally speaking the answer is probably no. It sounds like premature optimization.
One thing you might consider is making User a #Parent Ref<?> of UserAction. That way the parent will be fetched at the same time as the action in the same bulk get. As long as it fits your required transaction throughput (no more than 1 change per second for the whole User entity group), it should be fine.
In the smell Data Class as Martin Fowler described in Refactoring, he suggests if I have a collection field in my class I should encapsulate it.
The pattern Encapsulate Collection(208) says we should add following methods:
get_unmodified_collection
add_item
remove_item
and remove these:
get_collection
set_collection
To make sure any changes on this collection need go through the class.
Should I refactor every class which has a collection field with this pattern? Or it depends on some other reasons like frequency of usage?
I use C++ in my project now.
Any suggestion would be helpful. Thanks.
These are well formulated questions and my answer is:
Should I refactor every class which has a collection field with this
pattern?
No, you should not refactor every class which has a collection field. Every fundamentalism is a way to hell. Use common sense and do not make your design too good, just good enough.
Or it depends on some other reasons like frequency of usage?
The second question comes from a common mistake. The reason why we refactor or use design pattern is not primarily the frequency of use. We do it to make the code more clear, more maintainable, more expandable, more understandable, sometimes (but not always!) more effective. Everything which adds to these goals is good. Everything which does not, is bad.
You might have expected a yes/no answer, but such one is not possible here. As said, use your common sense and measure your solution from the above mentioned viewpoints.
I generally like the idea of encapsulating collections. Also encapsulating plain Strings into named business classes. I do it almost always when the classes are meaningful in the business domain.
I would always prefer
public class People {
private final Collection<Man> people;
... // useful methods
}
over the plain Collection<Man> when Man is a business class (a domain object). Or I would sometimes do it in this way:
public class People implements Collection<Man> {
private final Collection<Man> people;
... // delegate methods, such as
#Override
public int size() {
return people.size();
}
#Override
public Man get(int index) {
// Here might also be some manipulation with the returned data etc.
return people.get(index);
}
#Override
public boolean add(Man man) {
// Decoration - added some validation
if (/* man does not match some criteria */) {
return false;
}
return people.add(man);
}
... // useful methods
}
Or similarly I prefer
public class StreetAddress {
private final String value;
public String getTextValue() { return value; }
...
// later I may add more business logic, such as parsing the street address
// to street name and house number etc.
}
over just using plain String streetAddress - thus I keep the door opened to any future change of the underlying logic and to adding any useful methods.
However, I try not to overkill my design when it is not needed so I am as well as happy with plain collections and plain Strings when it is more suited.
I think it depends on the language you are developing with. Since there are already interfaces that do just that C# and Java for example. In C# we have ICollection, IEnumerable, IList. In Java Collection, List, etc.
If your language doesn't have an interface to refer to a collection regarless of their inner implementation and you require to have your own abstraction of that class, then it's probably a good idea to do so. And yes, you should not let the collection to be modified directly since that completely defeats the purpose.
It would really help if you tell us which language are you developing with. Granted, it is kind of a language-agnostic question, but people knowledgeable in that language might recommend you the best practices in it and if there's already a way to achieve what you need.
The motivation behind Encapsulate Collection is to reduce the coupling of the collection's owning class to its clients.
Every refactoring tries to improve maintainability of the code, so future changes are easier. In this case changing the collection class from vector to list for example, changes all the clients' uses of the class. If you encapsulate this with this refactoring you can change the collection without changes to clients. This follows on of SOLID principles, the dependency inversion principle: Depend upon Abstractions. Do not depend upon concretions.
You have to decide for your own code base, whether this is relevant for you, meaning that your code base is still being changed and has to be maintained (then yes, do it for every class) or not (then no, leave the code be).
Lets take a hypothetical project such as a student enrollment system for a music school.
Within the system there needs to exist a way to enter student data for a new student interested in receiving instruction at this school and we can assume that students may have access to this functionality through a web site.
Part of the enrollment process asks the student the type of instrument for which she would like to receive instruction.
As a result of entering information about her preferred musical instrument the behavior will be to assign a default instructor who is assigned to that group of instruments.
Before completing the enrollment request the student will be also be able to change the assigned instructor to different instructor who also is listed as able to give instructed for her selected instrument.
Given this description, the part I'm having a little trouble with is how manage the list of possible instructors out of the ones who are able to give instruction for particular instrument in terms of choosing a default instructor for a new student first, and secondly how to use this same data when it comes time to validate the selected instructor before an enrollment is submitted.
Other technical constraints are that up to this point I've been using a self validating technique very similar to the one presented in Jimmy Nilsson's book Applying Domain-Driven Design and Patterns so it is mainly unclear to me the best way to go about continuing following self validating techniques when access to external data is necessary which I would normally see as outside of the scope of the entity being tested for validity.
The options I'm aware of:
Move validation outside of the entity itself. Perhaps validation is moved into a set of services or a single service per entity which analyses current state of the whole entity and deems it valid or not and provides for domain events or other value objects to be emitted that give more insight about what validation rules have been broken. In this case I'm still a bit uneasy about how the service would get access to the necessary information about instructors
Allow for access to a instructor repository from necessary entities that are attempting to perform this validation.
Create a service that allows access to a list of instructors by instrument category. Alternatively create two separate services, one that returns whether a given instructor is in the list of instructors for a given category, and another which returns the default instructor for a given category.
Load a list of instructor value objects within my aggregate root (likely student, or a student enrollment request) that can be used for validation either by the aggregate root or entities contained within the root.
In either of the first two cases above it seems like the use of a instructor repository would be overkill because I don't need to access an aggregate root that represents an instructor but instead in my case I would see the instructor as a value object that describes the student enrollment request and having a repository spit back value objects seems to be blurring the lines of what a repository is supposed to be doing. For the last two options it seems wrong two allow access to data from a service or a factory in the case of option 4 since aren't repositories supposed to be in charge of data access such as this? And if repositories are the right place for this logic where are the appropriate places to access or store references to repositories? I've been convinced that there are reasons not to access repositories directly within any entity or value object that makes up the model so I'm wondering if this is a case where I may have to bend on that assumption. I should also mention that I'm pretty new to DDD and I'm just now encountering some of my head scratching moments and attempting not to box myself in so any knowledgeable input on this topic would be valuable.
Move validation outside of the entity itself.
One instructor shouldn't know about all other instructors. Validation against set of instructors isn't responsibility of one particular instructor.
Allow for access to a instructor repository from necessary entities that are attempting to perform this validation.
Domain model should be persistence ignorant. Need to break that indicates flaws in Your model.
Create a service that allows access to a list of instructors by instrument category.
This bit of information reveals lack of aggregate root - I would call it InstrumentClass.
Introducing that into Your model would solve some of Your issues. InstrumentClass would hold available instructors that teaches particular instrument.
Next thing You need to figure out is how to describe properly student that is assigned to class. Unfortunately I can't name it at the moment (maybe Participation?). But that entity would be used for InstrumentClass to figure out which instructors are too busy.
Here's my "free-style" (just to show what I see) on modeling Your domain:
using System;
public class Main{
public Main(){
var instructor = new Instructor();
var instrument = new Instrument("saxaphone");
var saxaphoneClass = new InstrumentClass(saxaphone,teacher);
var me=new Person("Arnis");
//here, from UI, I can see available classes, choose one
//and choose according instructor who's assigned to it
var request=me.RequestEnrollment(saxaphoneClass, instructor);
saxaphoneClass.EnrollStudent(request);
}
}
public class Person{
public IList<EnrollmentRequest> EnrollmentRequests { get; private set; }
public EnrollmentRequest RequestEnrollment
(InstrumentClass instrumentClass,Instructor instructor){
if (!instrumentClass.IsTeachedByInstructor(instructor))
throw new Exception("Instructor does not teach this music instrument");
var request=new EnrollmentRequest(this,instrumentClass,instructor);
EnrollmentRequests.Add(request);
return request;
}
}
public class EnrollmentRequest{
public Person Person{ get; private set; }
public InstrumentClass InstrumentClass { get; private set; }
public Instructor Instructor{ get; private set; }
}
public class InstrumentClass{
public void EnrollStudent(EnrollmentRequest request){
var instructor=request.Instructor;
var student=new Student(request.Person);
var studies=new Studies(this,student,instructor);
//TODO: this directiveness isn't good
//student/instructor should listen for class events themselves
//and class should listen if by any reason instructor or student cannot
//participate in studies
student.EnrollInClass(studies);
instructor.AssignStudent(studies);
Studies.Add(studies);
}
public bool IsTeachedByInstructor(Instructor instructor){
return Instructors.Contains(instructor);
}
public InstrumentClass
(Instrument instrument, params Instructor[] instructors){
Instrument=instrument; Instructors=instructors.ToList();
}
public IList<Instructor> Instructors{get;private set;}
public IList<Studies> Studies { get; private set; }
public Instrument Instrument { get; private set; }
}
public class Studies{
public Student Student { get; private set; }
public Instructor Instructor { get; private set; }
public InstrumentClass InstrumentClass { get; private set; }
}
public class Student{
}
public class Instructor{
}
public class Instrument{
}
My answer does not cover the detailed implementation / code as it seems that you are using this as an exercise to learn more about DDD.
Remember that in most cases you'll not be able to get the model right the first time and need to evolve the model. As you “play with it” certain rigid parts will become more flexible to change. (Like a gardening glove as per Eric's analogy). As you gain new insights into the domain, you'll find that you need to introduce new concepts into your model. Using “simple examples” has dangers for example they can lack depth. But simple examples are sometimes needed to get the hang of DDD and fortunately we can evolve the example too ;)
One thing I've heard Eric Evans mention was that if the domain does not feel right or you have trouble expressing something in a model you might be missing a concept. Naturally if you have the concepts in your domain you can “get a feeling” or find a natural place where validation will occur.
Having set the context I thus have a proposition as follow:
Enterprise Patterns and MDA has some complex patterns but the idea you can take away is the CapacityManager of the Inventory archetype as guidance. Unfortunately the model on pg 278 is not available online but have a look at the ServiceInventory archetype.
The instructors are selling their services to students. (Instructors get a salary last time I checked :). If I were to map your example to the Inventory archetype for ideas I would use:
Inventory - List of instruments/courses
ServiceType - Instrument / Course details, start end etc
ServiceInventoryEntry - Instrument + places available (uses capacity manager)
ServiceInstance - Enrollment - place in class (Scheduled, Booked, Canceled, Completed)
CapacityManager (used by ServiceInventoryEntry)
ReservationRequest - Enrollment request
I think the key concept added is the CapacityManager: You can call the ServiceInventoryEntry::getCourses() method which will use the CapacaityManager (service or class) to show you / calculate the available teachers or return the default one. Thus, call it multiple times depending on the context: Default or Propose a list of available places/seats/instructors.
With this model you should be able to find natural place (where and when) to validate. The guidance from Streamlined Object Modeling is to put validation where the data is. Not to be taken as a hard rule but there is a natural tendency for objects to have the proper concerns and data grouped together. For example the capacity manager knows about enrollments and instruments. (From MDA - CapacityManger: Manages utilization of capacity by releasing ServiceInstances)
To get your aggregates see what transactions / changes you'll do so that you can ensure they enforce the invariants (rules). In your example I would make ServiceType(Course) a value object, ServiceInventoryEntry and ReservationRequests aggregate roots. (Depends on how complex you want to take your rules). You can also add Students and Teachers as parties as per the MDA book. I tend to use repositories to get hold of my aggregates and then also rely on inversion of control as per Jimmy's book you referenced.
The reason I like the MDA patterns is that it makes me think of use cases and model concepts that I or the business would not have imagined. But, be careful to only model what you need since the MDA patterns can be big and even enticing. The good thing is that they are designed to be modular or "down scalable".
So in short:
- Your aggregate roots should ensure your domain is in a valid state (Rules / Invariants)
- Put the validation where the data is. Your model will guide your.
The Wikipedia article about encapsulation states:
"Encapsulation also protects the integrity of the component, by preventing users from setting the internal data of the component into an invalid or inconsistent state"
I started a discussion about encapsulation on a forum, in which I asked whether you should always clone objects inside setters and/or getters as to preserve the above rule of encapsulation. I figured that, if you want to make sure the objects inside a main object aren't tampered with outside the main object, you should always clone it.
One discussant argued that you should make a distinction between aggregation and composition in this matter. Basically what I think he ment is this:
If you want to return an object that is part of a composition (for instance, a Point of a Rectangle), clone it.
If you want to return an object that is part of aggregation (for instance, a User as part of a UserManager), just return it without breaking the reference.
That made sense to me too. But now I'm a bit confused. And would like to have your opinions on the matter.
Strictly speaking, does encapulation always mandate cloning?
PS.: I program in PHP, where resource management might be a little more relevant, since it's a scripted language.
Strictly speaking, does encapulation always mandate cloning?
No, it does not.
The person you mention is probably confusing the protection of the state of an object with the protection of the implementation details of an object.
Remember this: Encapsulation is a technique to increase the flexibility of our code. A well encapsulated class can change its implementation without impacting its clients. This is the essence of encapsulation.
Suppose the following class:
class PayRoll {
private List<Employee> employees;
public void addEmployee(Employee employee) {
this.employees.add(employee);
}
public List<Employee> getEmployees() {
return this.employees;
}
}
Now, this class has low encapsulation. You can say the method getEmployees breaks encapsulation because by returning the type List you can no longer change this detail of implementation without affecting the clients of the class. I could not change it for instance for a Map collection without potentially affecting client code.
By cloning the state of your object, you are potentially changing the expected behavior from clients. This is a harmful way to interpret encapsulation.
public List<Employee> getEmployees() {
return this.employees.clone();
}
One could say the code above improves encapsulation in the sense that now addEmployee is the only place where the internal List can be modified from. So If I have a design decision to add the new Employee items at the head of the List instead of at the tail. I can do this modification:
public void addEmployee(Employee employee) {
this.employees.insert(employee); //note "insert" is used instead of "add"
}
However, that is a small increment of the encapsulation for a big price. Your clients are getting the impression of having access to the employees when in fact they only have a copy. So If I wanted to update the telephone number of employee John Doe I could mistakenly access the Employee object expecting the changes to be reflected at the next call to to the PayRoll.getEmployees.
A implementation with higher encapsulation would do something like this:
class PayRoll {
private List<Employee> employees;
public void addEmployee(Employee employee) {
this.employees.add(employee);
}
public Employee getEmployee(int position) {
return this.employees.get(position);
}
public int count() {
return this.employees.size();
}
}
Now, If I want to change the List for a Map I can do so freely.
Furthermore, I am not breaking the behavior the clients are probably expecting: When modifying the Employee object from the PayRoll, these modifications are not lost.
I do not want to extend myself too much, but let me know if this is clear or not. I'd be happy to go on to a more detailed example.
No, encapsulation simply mandates the ability to control state by creating a single access point to that state.
For example if you had a field in a class that you wanted to encapsulate you could create a public method that would be the single access point for getting the value that field contains. Encapsulation is simply this process of creating a single access point around that field.
If you wish to change how that field's value is returned (cloning, etc.) you are free to do so since you know that you control the single avenue to that field.