- Home
- LLBLGen Pro
- Architecture
Creating new objects
Joined: 20-Dec-2004
Hi, I had another question. Say that I want to create a new User object which basically translates to an insert in the DB. I think the code you suggest is the following:
User user = new User(); //populate all properties of the user object
User.Save();
Say that the business rule is that UserId and FirstName is required field.
But my concern with your framework is that it allows you to create a user object which does not have all it values properly initialized. Say that FirstName is a required field and the programmer forgets to populate this field. In this case the only error I get is a runtime error. Also typically this code I just wrote will be in the Code Behind/Presentation Layer. I would like the GUI not to know anything about the business logic that the firstName is a required field. Wouldn't it be better to create a constructor of this form
User user = new User(UserId, FirstName)
This way a programmer cannot create a User object which is not properly intialized. I am not trying to say what you guys have done is wrong but I am just trying to understand your logic. thanks
Joined: 23-Apr-2004
I'll refer you to the Manager Classes again here (http://llblgen.com/tinyforum/Messages.aspx?ThreadID=1892)... they have Create methods which take the minimum required fields as parameters. This ensures that the entity is properly constructed and all required fields are populated.
Joined: 17-Aug-2003
kulki wrote:
Hi, I had another question. Say that I want to create a new User object which basically translates to an insert in the DB. I think the code you suggest is the following:
User user = new User(); //populate all properties of the user object
User.Save();
Say that the business rule is that UserId and FirstName is required field.
But my concern with your framework is that it allows you to create a user object which does not have all it values properly initialized. Say that FirstName is a required field and the programmer forgets to populate this field. In this case the only error I get is a runtime error. Also typically this code I just wrote will be in the Code Behind/Presentation Layer. I would like the GUI not to know anything about the business logic that the firstName is a required field. Wouldn't it be better to create a constructor of this form
User user = new User(UserId, FirstName)
This way a programmer cannot create a User object which is not properly intialized. I am not trying to say what you guys have done is wrong but I am just trying to understand your logic. thanks
If you want to check this, you can implement IEntityValidator and add a validator object to the entity which validates teh fields when entity.Validate() is called, which is called when the entity is saved for example.
The method approach is not that great, as when you add a field later on, you have to alter all constructor calls. Better is to use properties to set fields. Indeed, if a programmer misses a mandatory field this will result in flaws, but that's the responsibility of the developer. If the developer doesn't save the entity it also doesn't work (to name a trivial example)
Joined: 23-Apr-2004
Otis wrote:
The method approach is not that great, as when you add a field later on, you have to alter all constructor calls. Better is to use properties to set fields. Indeed, if a programmer misses a mandatory field this will result in flaws, but that's the responsibility of the developer. If the developer doesn't save the entity it also doesn't work (to name a trivial example)
Yes I agree that changes to the DB will cause code to break which can be a pain, but then I prefer compile time breakages rather than run time... But I certainly take your point.
Joined: 20-Dec-2004
Well thats why I personally don't like to have to call entity.Save(). I would much rather simply called UnitofWork.COmmit(). This way the developer does not need to track what objects need to be saved.
Also the way I think is that one should not be able to create objects which are not properly intialized. I would assume that if there is an object in memory then it is intialized.
Joined: 20-Dec-2004
Otis wrote:
If you want to check this, you can implement IEntityValidator and add a validator object to the entity which validates teh fields when entity.Validate() is called, which is called when the entity is saved for example.
The method approach is not that great, as when you add a field later on, you have to alter all constructor calls. Better is to use properties to set fields. Indeed, if a programmer misses a mandatory field this will result in flaws, but that's the responsibility of the developer. If the developer doesn't save the entity it also doesn't work (to name a trivial example)
Well the validator method is invoked only when the save method gets invoked. Which means that I could have an invalid object in memory until I call the Save method. Don't you think its a much cleaner solution not to have an invalid object at all.
Joined: 04-Feb-2004
Marcus wrote:
Yes I agree that changes to the DB will cause code to break which can be a pain, but then I prefer compile time breakages rather than run time... But I certainly take your point.
I have found that the looser the coupling between the interfaces the better. So by having Controller.Save(entityToSave) you have a very loose coupling. I used to write very granular interfaces, i.e. Save(field1, field2, field3) but when using COM+ thats a deployment nightmare.
kulki wrote:
Well the validator method is invoked only when the save method gets invoked. Which means that I could have an invalid object in memory until I call the Save method. Don't you think its a much cleaner solution not to have an invalid object at all.
I was under the impression that if default values were specified at the database field level then when the save occurred the defaults would be used if not set in the entity, thus always ensuring that a proper object was saved in the event that the developer didnt fill in all fields.
Also, for that matter, IMO you are never going to be able to 100% cover all fields during object instanciation. For example, if the OrderTotal field depends on price and quantity about all you could ever do during instanciation is ensure that the field was = 0 if it was numeric.
Also, IMO at some point, your developers writing code for the middle tier will need to become familiar with the entities and their meaning and scope as it applies to the business / problem domain at hand.
Joined: 17-Aug-2003
kulki wrote:
Well thats why I personally don't like to have to call entity.Save(). I would much rather simply called UnitofWork.COmmit(). This way the developer does not need to track what objects need to be saved.
A developer always has to do that, because in 9 out of 10 times the developer has to deal with some sort of business logic layer which takes care of the business rules. And no, how fowler/evans want you to use BL, i.e. cram everyting inside the entity classes, is not the way to go in the long run, as you run into problems soon enough because BL is scattered all over the place and there is no clear connection between the functional design of the functionality and the actual implementation (which is recognized by Evans by his remark that there should be some sort of translation language for that (so instead of fixing the problem in the first place, a fix for a symptom of the problem is suggested... )). Fowler doesn't have this problem from his POV as he is in the XP/agile camp.
Also the way I think is that one should not be able to create objects which are not properly intialized. I would assume that if there is an object in memory then it is intialized.
An entity that's not in the database is not defined by definition. This is a key aspect of working with entities. Anyone who claims an entity exists whenever you've instantiated it, hasn't thought about a multi-user application that's spread over multiple machines (2 desktops, 1 server, or 2 or more webservers in a webfarm as examples)
Joined: 20-Dec-2004
Otis wrote:
A developer always has to do that, because in 9 out of 10 times the developer has to deal with some sort of business logic layer which takes care of the business rules. And no, how fowler/evans want you to use BL, i.e. cram everyting inside the entity classes, is not the way to go in the long run, as you run into problems soon enough because BL is scattered all over the place and there is no clear connection between the functional design of the functionality and the actual implementation (which is recognized by Evans by his remark that there should be some sort of translation language for that (so instead of fixing the problem in the first place, a fix for a symptom of the problem is suggested... )). Fowler doesn't have this problem from his POV as he is in the XP/agile camp.
Well my main concern with calling Entity.Save() is that the GUI developer needs to know what objects have been modified in the first place. In a large complex project I don't think thats a valid assumption. But in my case I am willing to live with it.
Otis wrote:
An entity that's not in the database is not defined by definition.
Thats an interesting idea. I was wondering if there is any material you could direct me to where I can read about this. I do see your point, but in the extreme case that there is no DB are u suggesting that there can be no entities? I think that the only reasons we need a DB is because we don't have unlimited memory. In a hypothetical scenario with unlimited memory I would simply not use a DB and purely have objects in memory.
Joined: 17-Aug-2003
kulki wrote:
... Well my main concern with calling Entity.Save() is that the GUI developer needs to know what objects have been modified in the first place. In a large complex project I don't think thats a valid assumption. But in my case I am willing to live with it.
Since when does a developer not know which objects are changed if he does write the code to change the objects? And even then, a non-changed object is simply skipped by the engine so it's not that important.
Otis wrote:
An entity that's not in the database is not defined by definition.
Thats an interesting idea. I was wondering if there is any material you could direct me to where I can read about this. I do see your point, but in the extreme case that there is no DB are u suggesting that there can be no entities? I think that the only reasons we need a DB is because we don't have unlimited memory. In a hypothetical scenario with unlimited memory I would simply not use a DB and purely have objects in memory.
A database serves another role as well: the only central repository where the application state is stored. With multiple users on a system, there is just 1 core part of the complete application which is the same for all: the database.
An entity is the data in an entitydefinition implementation in the database: the data in a row in a table. An entity therefore isn't 'existend' when you fill an instance of an entity-representing class with some data, until you save it in the database. As was mentioned earlier: if you use a sequenced PK or you define defaults in the db, you don't get these values back until you save the entity (that is, the data). Read the concepts in the documentation for more details. Fowler/evans define entity as something outside the database, which IMHO is wrong, as that's a plain re-definition of a wellknown definition.
Joined: 20-Dec-2004
Otis wrote:
Since when does a developer not know which objects are changed if he does write the code to change the objects? And even then, a non-changed object is simply skipped by the engine so it's not that important.
Well say that the GUI developer does not have access to the Business Objects. Its then entirely possible for the GUI developer not to know about objects which BL might create and not expose to the GUI. Say that when I change the the firstName of a user a new Log entity is automatically created and this object is not exposed to the GUI at all.
Now the GUI might have the following code. User user = new User("Otis"); user.FirstName = Frans; UnitOfWork uow = new UnitOfWOrk(); uow.AddForSave(user); uow.Commit(); Now how does the log entity add itself to the transaction?
Otis wrote:
An entity is the data in an entitydefinition implementation in the database: the data in a row in a table. An entity therefore isn't 'existend' when you fill an instance of an entity-representing class with some data, until you save it in the database. As was mentioned earlier: if you use a sequenced PK or you define defaults in the db, you don't get these values back until you save the entity (that is, the data). Read the concepts in the documentation for more details. Fowler/evans define entity as something outside the database, which IMHO is wrong, as that's a plain re-definition of a wellknown definition.
Well this gives rise the issue of inserts when the DB generates the Pkey. Say that you have a parent object as well as a child object which are both created. How do you handle the logic that parent must be first inserted, then the based on the PK of the parent update the child's FK and then insert the child? Do we write any code to support this feature or does OR mapper handle this.
Joined: 20-Dec-2004
Also in your opinion whats should be the right behaviour under the following circumstances.
a) I create a entity object using the follwing code: UserEntity user = new UserEntity(); String firstName = user.FirstName;
Just throw an exception?
b) Say that Email address is a not a required field i.e. EmailAddress is a nullable. In my architecture I ended up using a DateType called NullableString which BTW can be downloaded from sourceforge. But in the code generator it only produces a datatype called string and not NullableString. How do I update EmailAdress such that a null value is stored in the Database?
Joined: 20-Dec-2004
kulki wrote:
Also in your opinion whats should be the right behaviour under the following circumstances.
a) I create a entity object using the follwing code: UserEntity user = new UserEntity(); String firstName = user.FirstName;
Just throw an exception?
b) Say that Email address is a not a required field i.e. EmailAddress is a nullable. In my architecture I ended up using a DateType called NullableString which BTW can be downloaded from sourceforge. But in the code generator it only produces a datatype called string and not NullableString. How do I update EmailAdress such that a null value is stored in the Database?
I guess my follow up question would be is there a way for me to change the code generator so that nullable strings become NullableStrings instead of strings.
Joined: 17-Aug-2003
kulki wrote:
Otis wrote:
Since when does a developer not know which objects are changed if he does write the code to change the objects? And even then, a non-changed object is simply skipped by the engine so it's not that important.
Well say that the GUI developer does not have access to the Business Objects. Its then entirely possible for the GUI developer not to know about objects which BL might create and not expose to the GUI. Say that when I change the the firstName of a user a new Log entity is automatically created and this object is not exposed to the GUI at all.
Now the GUI might have the following code. User user = new User("Otis"); user.FirstName = Frans; UnitOfWork uow = new UnitOfWOrk(); uow.AddForSave(user); uow.Commit(); Now how does the log entity add itself to the transaction?
I completely miss the point of having a gui which can't communicate with BL objects.
Otis wrote:
An entity is the data in an entitydefinition implementation in the database: the data in a row in a table. An entity therefore isn't 'existend' when you fill an instance of an entity-representing class with some data, until you save it in the database. As was mentioned earlier: if you use a sequenced PK or you define defaults in the db, you don't get these values back until you save the entity (that is, the data). Read the concepts in the documentation for more details. Fowler/evans define entity as something outside the database, which IMHO is wrong, as that's a plain re-definition of a wellknown definition.
Well this gives rise the issue of inserts when the DB generates the Pkey. Say that you have a parent object as well as a child object which are both created. How do you handle the logic that parent must be first inserted, then the based on the PK of the parent update the child's FK and then insert the child? Do we write any code to support this feature or does OR mapper handle this.
No you don't have to do anything, the O/R mapper core takes care of this. You can save a graph from any point, even the lowest leave, and it is saved in teh right order. It doesn't matter if you setup the graph in the gui and pass it on to another layer or remoted service either.
kulki wrote:
Also in your opinion whats should be the right behaviour under the following circumstances. a) I create a entity object using the follwing code: UserEntity user = new UserEntity(); String firstName = user.FirstName;
Just throw an exception?
All fields have a default value, defined in TypeDefaultValue.cs/vb (or typeDefaultValue.template) which is returned in this case.
b) Say that Email address is a not a required field i.e. EmailAddress is a nullable. In my architecture I ended up using a DateType called NullableString which BTW can be downloaded from sourceforge. But in the code generator it only produces a datatype called string and not NullableString. How do I update EmailAdress such that a null value is stored in the Database?
See: "Using the generated code / Selfservicing (or adapter) / Using the entity classes -> Entities, NULL values and defaults". It's pretty straightforward.
NullableTypes is a library I'm aware of, but our code is not relying on 3rd party libs for functionality plus the types have to be pure .NET types, not some type in a 3rd party library because that gives problems in VB.NET.