Field modifiers

Posts   
 
    
jopa
User
Posts: 14
Joined: 17-Feb-2007
# Posted on: 19-Feb-2007 13:15:11   

Is there a way to set modifiers of entity fields using generator. I want some fields to be private or protected. For example I want my generated class to look like this:

class Contact { public string Name; protected int ContactType; }

Then I would extend generated class with my own code to expose public enum ContactType.

Aurelien avatar
Aurelien
Support Team
Posts: 162
Joined: 28-Jun-2006
# Posted on: 19-Feb-2007 15:40:50   

Hi,

I guess you mean property, all fields are private in entities.

Cou can easyly overload property :


class Contact
{

  public int ContactType
  {
    get
    {
       ...
    }
  }

}

and the inherited class :


class SubContact
{

  public new ContactTypeEnum ContactType
  {
    get
    {
       ...
    }
  }

}
jopa
User
Posts: 14
Joined: 17-Feb-2007
# Posted on: 19-Feb-2007 16:05:02   

Yap, but I'm not inheriting classes. I'm using partial classes to implement my business logic. And second thing, I want to hide int ContactType from other users that will use my class in their code. So i want that property to be protected or private.

Aha, sorry, now is see "new ContactType". I don't like this kind of hiding base class members. Anyway thanks

Posts: 1263
Joined: 10-Mar-2006
# Posted on: 19-Feb-2007 16:54:22   

Interesting request.

I can see that need/desire. Would be great if you could flag a field in the designer to be a protected property.

In SS, 2 class scenario - you can override any property to handle any special behaviors, but of course you cannot change the return type or hide it from the class (which you are trying to do both things).

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 19-Feb-2007 17:03:26   

jopa wrote:

Yap, but I'm not inheriting classes. I'm using partial classes to implement my business logic. And second thing, I want to hide int ContactType from other users that will use my class in their code. So i want that property to be protected or private.

How would you then set it to a value? If contacttype is a discriminatorvalue it's readonly anyway so setting it to a value will result in an error.

Do you want to control the get/set of the field ? I'm trying to get a clear image about why people would want this. The request has been made before, though I never could come up with a proper use-case to justify the addition, simply because validation etc. is done with validator objects for example, so that code doesn't have to be placed inside property getters/setters.

So if you could elaborate a bit why you want to hide an entity field's property and add your own in code, I might get a better understanding why you want this.

For type changes, you can use a typeconverter. Type converters can then for example convert an int to your enum type and the field is property typed to your enum, and the value is converted automatically at runtime transparently for you by the typeconverter class. You can write them yourself, they're very straightforward and small. As you're a demouser, you could have a look inside the typeconverters dll with reflector.

(edit). Typically, what we want to avoid is scattered around logic inside properties if you can centralize it inside an object which is injected via IoC at runtime, for example the validator objects.

Frans Bouma | Lead developer LLBLGen Pro
jopa
User
Posts: 14
Joined: 17-Feb-2007
# Posted on: 19-Feb-2007 17:03:41   

That's right Wayne! Encapsulation to the people simple_smile

jopa
User
Posts: 14
Joined: 17-Feb-2007
# Posted on: 19-Feb-2007 17:11:43   

Ok here's one possible situation: My resposibility is to create Contact class:

public enum ContactRegion
{
  Europe,
  Asia,
  USA,
  Etc
}

public class Contact
{
  public int ID;
  private int region;
  public ContactRegion Region
  {
    get { return Enum.Parse(typeof(ContactRegion), region); }
    set { this.region = (int)value; }
  }
}

So, what I want is to store int value in database but to expose Enum value to other team members that will use my class. I wrote this from my head so I don't now if it would compile. I don't have ContactRegion table in the database. If this is not clear enough I can make a small example tonight?

jopa
User
Posts: 14
Joined: 17-Feb-2007
# Posted on: 19-Feb-2007 17:15:40   

Aha, did not catch type converters. That's fine, but there are other situations where you don't want to expose some fields publicly but to use them inside that class.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 19-Feb-2007 17:21:40   

jopa wrote:

Ok here's one possible situation: My resposibility is to create Contact class:

public enum ContactRegion
{
  Europe,
  Asia,
  USA,
  Etc
}

public class Contact
{
  public int ID;
  private int region;
  public ContactRegion Region
  {
    get { return Enum.Parse(typeof(ContactRegion), region); }
    set { this.region = (int)value; }
  }
}

So, what I want is to store int value in database but to expose Enum value to other team members that will use my class. I wrote this from my head so I don't now if it would compile. I don't have ContactRegion table in the database. If this is not clear enough I can make a small example tonight?

I see your point, but as I pointed out, you can do this with a typeconverter. The type converter then converts the int to /from the enum for you transparently and entity field has the type of your enum all the way (also in the EntityField object, which is for example used in typed lists or dynamic lists).

Espcially that last bit is important. Say you want to fetch a list of aggregated data and your Region field is also in that list. LLBLGen Pro will then convert the int values to enum values as well, without you to worry about adding logic for it.

I've attached the sourcecode of the BooleanNumericTypeConverter which ships with llblgen pro (which converts a numeric value to a boolean and back, which can be used to get bool fields on oracle for example).

It gives you an idea how these objects work. The LLBLGen Pro SDK contains more information about how to write typeconverters.

If you have another usage scenario for this, please let me know, because if it's indeed a good scenario I can try to look for features to add to v2.1 (or tweak if they're already there) so this functionality gets added. simple_smile

Attachments
Filename File size Added on Approval
BooleanNumericConverter.cs 10,696 19-Feb-2007 17:22.04 Approved
Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 19-Feb-2007 17:23:42   

jopa wrote:

Aha, did not catch type converters. That's fine, but there are other situations where you don't want to expose some fields publicly but to use them inside that class.

Could you elaborate a bit on this?

Because to me, these fields should then be hidden overall, thus also not be able to show up in typedlists / dynamic lists etc. (because with that route you can still obtain the values).

So my question then is: if that's so, how would you fill these fields with data? When other fields are set to a given value for example?

Frans Bouma | Lead developer LLBLGen Pro
jopa
User
Posts: 14
Joined: 17-Feb-2007
# Posted on: 19-Feb-2007 17:54:52   

I'm still learning your framework, so maybe I'm missing something out there. I know that you get different requests every day and that is very hard to implement different use cases inside framework that will still be easy to use and understand. I apologies my self if my questions are bothering you. I’ve been using other frameworks/generators (IdeaBlade, EntitySpaces and other) and have 10 years experience in enterprise solutions. There are so many things I like about llblgen, and right now I’m trying to convince my team members to use it on our next project.

It is very common demand in programming to encapsulate some information into the class itself. That does not mean that this information is not persistable. What I want from generated code is to allow me to hide some information inside class by marking that field as protected, so it can be used by that class and it’s ancestors, but not other classes that use that class. So, I want to mark mapped field in designer as protected (or private or internal protected or whatever). Code:

Class Contact
{
    //generated fields
    private int id; 
    private int somePersistableInfomation; 
    
    //generated property VISIBLE outside this class
    public int Id
    {
        get {return id;}
        set { id = value;}
    }

    //generated property NOT VISIBLE outside this class
    protected SomePersistableInformation 
    {
        get {return somePersistableInformation;}
        set { somePersistableInformation = value;}
    }

    public void DoSomething()
    {
        this.SomePersistableInformation = 100;
    }
}

Again, this is not major issue, if there is a workaround it's good enough for me. Just asking am I missing something. Thanks

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 20-Feb-2007 07:48:31   

IMHO, encapsulating doesn't only mean hide data, but hide access implementation. In other words "add behavior to the accessor methods". As I see in LLBLGenPro the data remains hidden and the Property Accesors (you could override) and the ValidatorClasses permit you to modify the way clients interacts with the data. Martin Flower says: "... its much better for encapsulated data to look the same as public data...". (http://www.martinfowler.com/ieeeSoftware/dataAccessRoutines.pdf-recommended to this point-wink )

I have make some projects in LLBLGenPro: the majority in Adapter scenario. And in both cases (Adapter and SelfServicing) I canned to hide the data access behavior without sacrifice the public access, as I see that (protected properties) as a dark thing (not bad, but dark), IMHO. I would secure the way one module interacts with other (for example GUI interacting with DatabaseSpecific DLL without let it now to my BL Modules), but that's another history (securing malicious coding). disappointed

Anyway, I prefer to work with a set of plain and only-data classes (all public) and a set of modules (business logic) to provide behaviors to these set of classes. So the data that I want to hide in one place I could need to be public in other places, so the behaviors (your business logic) makes the difference. However, the world is big. Until now, I didn't need that approach (protect some fields - better, properties -). But maybe you did. Could you elaborate an example of that need? frowning

David Elizondo | LLBLGen Support Team
jopa
User
Posts: 14
Joined: 17-Feb-2007
# Posted on: 20-Feb-2007 10:21:42   

Fowler is great. I bought his Patterns of EAA a year ago . So in that artcle he says, Figure 4:

class Person {
public String Name {
get {
  return _firstName + “ “ + _lastName;
}
set {
 String[] words = value.Split(‘ ‘);
  if (words.Length != 2)
  throw new Exception (“name can only have two words”);
  _firstName = words[0];
  _lastName = words[1];
}
}
private String _firstName;
private String _lastName;

See, public string Name is property visible outside of this class. But in database we have two fields FirstName and LastName. But they are not visible to the consumer of this class. You can not bind FirstName to a text box on a form, but FullName you can.

Anyway, I prefer to work with a set of plain and only-data classes (all public) and a set of modules (business logic) to provide behaviors to these set of classes.

Not sure if I get this right? You use llblgen to generate DTO's (data transfer objects), and implement business logic in some other classes that consume that DTO's. In my scenario (SS), business logic is implemented in the same class that contains data, and knows how to persist that data.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 20-Feb-2007 18:21:05   

Not sure if I get this right? You use llblgen to generate DTO's (data transfer objects), and implement business logic in some other classes that consume that DTO's. In my scenario (SS), business logic is implemented in the same class that contains data, and knows how to persist that data.

Only chance the pattern but you still have behavior in two scenarios. For example in both Adapter and SS you could override Properties and make validations via ValidatorClasses, only chance the owner of the persistence functions.

About encapsulation I think I got your point. The Fowler code at Figure 4 illustrate how to preserve the interface after some data structures changes (the origin of the need is not to hide data, but preserve the interface). Same example in LLBLGen we could have (as Figure 3):


...

// LLBL CODE
public virtual string Name
{
     get {logic to return data to field _name;}
     set {logic to set data to field _name}
}

and after the structure changes...

...

// LLBL CODE
public virtual string FirstName
{
     get {logic to return data to field _firstName;}
     set {logic to set data to field _firstName}
}

public virtual string LastName
{
     get {logic to return data to field _lastName;}
     set {logic to set data to field _lastName}
}

// CUSTOM CODE: PRESERVING THE INTERFACE
public string Name
{
     get {logic to return data to fields _firstName + lastName;}
     set {logic to set data to fields _firstName + lastName}
}

However, the Properties that access the two new fields are visible and accessible. We could modify the accessibility by override the behavior but not the visibility (I see your point simple_smile ). Mmhhmm disappointed The fields always are private, but not property accesors. So we could preserve the interface but no hide added stuff. It's that wrong?

I'm thinking right now at your points.. disappointed ...

David Elizondo | LLBLGen Support Team
jopa
User
Posts: 14
Joined: 17-Feb-2007
# Posted on: 21-Feb-2007 09:30:00   

The fields always are private, but not property accesors. So we could preserve the interface but no hide added stuff. It's that wrong?

That's right. Property accessors should be user defined. Default should be "public" but for some properties I want to set other modifier like "private" or "protected". When editing entity fields using designer, I can set "readonly" for field, why can't I set "protected"

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 21-Feb-2007 10:52:45   

The properties have to be there, because they contain getter/setter logic for the value, so they call the methods to set a value (which then will validate etc. the stuff) and the get data.

I don't think FullName is a proper example for this feature, as you still need to have firstname and lastname to SET these, as I think setting these from a Fullname property isn't really reliable.

HOWEVER, I think with the enum thing it indeed can get a bit awkward (see also this thread: http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=9064 )

So, if a field is marked private or protected, it should have its property be marked protected or private, though does it also have to have its name be suffixed or prefixed? I think that's better (e.g suffixed with 'Impl') because it then will allow you to add a property in code which has the actual name of the field. Otherwise you'd have to create a new property.

there's a problem with databinding and xml serialization, but that can be solved.

I've to think about it, it does give developers way more flexibility though, and that's always a big plus as code generation already has the name of being too rigid.

I'll think about it. I'll add it as level 1 feature to v2.1's featurelist, as I don't see big problems for it.

Frans Bouma | Lead developer LLBLGen Pro
jopa
User
Posts: 14
Joined: 17-Feb-2007
# Posted on: 21-Feb-2007 14:05:51   

So, if a field is marked private or protected, it should have its property be marked protected or private, though does it also have to have its name be suffixed or prefixed?

I think that prefixing or suffixing a property name is not necessary. It is already possible to rename a property in the model designer, so if I want to rename it I will do it manually. Thanks!

Posts: 1263
Joined: 10-Mar-2006
# Posted on: 21-Feb-2007 18:00:34   

So, if a field is marked private or protected, it should have its property be marked protected or private, though does it also have to have its name be suffixed or prefixed? I think that's better (e.g suffixed with 'Impl') because it then will allow you to add a property in code which has the actual name of the field. Otherwise you'd have to create a new property.

Sounds like a good feature to add and initially I was thinking you would not need the suffix, but I think you are right. If you did not suffix it, then you could not publish a property of that name.....

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 22-Feb-2007 10:00:17   

WayneBrantley wrote:

So, if a field is marked private or protected, it should have its property be marked protected or private, though does it also have to have its name be suffixed or prefixed? I think that's better (e.g suffixed with 'Impl') because it then will allow you to add a property in code which has the actual name of the field. Otherwise you'd have to create a new property.

Sounds like a good feature to add and initially I was thinking you would not need the suffix, but I think you are right. If you did not suffix it, then you could not publish a property of that name.....

Exactly, so the enum approach then can't work.

I though have a bit of a problem with dyn. lists and typedlists: what if a private field has to be added to a dyn. list? The field object IS there... also, the field IS in the fieldindex, so a developer could call entity.GetCurrentFieldValue(index) or entity.Fields[index].CurrentValue

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1263
Joined: 10-Mar-2006
# Posted on: 22-Feb-2007 15:59:04   

also, the field IS in the fieldindex, so a developer could call entity.GetCurrentFieldValue(index) or entity.Fields[index].CurrentValue

True. So, it would not be 'completely' hidden and there would be a way around the protection to write directly to the field. Probably still ok. Sort of like the primary key property being read-only and you cannot write to it....UNLESS you call the 'force***' method.

I though have a bit of a problem with dyn. lists and typedlists: what if a private field has to be added to a dyn. list? The field object IS there...

I guess this then be another way around the encapsulated property?

I though have a bit of a problem

....yuck, change has lots of other impacts...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 24-Feb-2007 12:07:21   

WayneBrantley wrote:

also, the field IS in the fieldindex, so a developer could call entity.GetCurrentFieldValue(index) or entity.Fields[index].CurrentValue

True. So, it would not be 'completely' hidden and there would be a way around the protection to write directly to the field. Probably still ok. Sort of like the primary key property being read-only and you cannot write to it....UNLESS you call the 'force***' method.

True. So it's more of a convenience feature than a protection against lame developers. I still find it a bit hard to program features which hide stuff for developers. If you don't trust your developers, fire them.

I though have a bit of a problem with dyn. lists and typedlists: what if a private field has to be added to a dyn. list? The field object IS there...

I guess this then be another way around the encapsulated property?

Yes, so the field which is hidden for the entity, still is there. I'm not sure if I like it that much though...

I though have a bit of a problem

....yuck, change has lots of other impacts...

Yes... disappointed I'm not sure if I like the side effects. Though I understand the necessity for it in other areas...

Frans Bouma | Lead developer LLBLGen Pro