Isn't selfservicing evil?

Posts   
 
    
BlueCell avatar
BlueCell
User
Posts: 83
Joined: 12-Jul-2004
# Posted on: 06-Nov-2005 17:12:09   

Hi,

After some toughts the question "Isn't selfservicing evil?" kept spooking inside my head. I must have read these sentences a 1000 times (ok a little bit exaggerated, but still...): - "Adapter is about the paradigm that persistence is a 'service'." - "SelfServicing is about the paradigm that object persistence is something about the objects being persisted."

Ok, this kind of leaves you to decide for yourself what to use. But still, isn't SelfServicing like when you put a "press here to nuke the world" button in front of the whitehouse, in stead of hiding it somewhere deep inside a bunker 1000 km's below surface?

BC

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39749
Joined: 17-Aug-2003
# Posted on: 06-Nov-2005 18:17:45   

hehe simple_smile Naah, I don't think you should see it like that. I think for a lot of projects, you don't need adapter's characteristic features, and in some projects you have to use adapter because of them. Some people are puristic about it and make a decision what is 'right' and what is 'wrong': a true DDD oriented developer/architect probably won't opt for selfservicing precisely for the fact that an entity has a 'save' method. Others are more pragmatical and think "that's handy!".

That's also the reason why both are first class citizens and won't be thrown out because of a better option. This forum (most of it, some is still old LLBLGen 1.x code) runs on selfservicing code for example, as does our website's CMS page renderer engine (edit tool is still asp/COM). Though the tool I use to manage change logs and build parameters for finalbuilder is written with adapter, e.g.: sometimes I pick a, sometimes I pick b. For this forum, I use a BL tier, which shows it might have been better if I would have picked adapter, (though adapter wasn't around when I started with the code wink , because it wouldn't lead to shortcuts where persistence methods are called in code-behind pages (I never do that, but if I wanted to, I could). So in that view, you're probably right: in a team where you can't really trust the guy in the corner who does all the gui programming, it might not be a good idea to hand a set of objects to that person if those objects offer persistence logic, so a carefully crafted BL tier is circumvented (We all know what kind of weird things are invented to make a deadline). But in an app with 2 tiers, for example a desktop app, why not use selfservicing?

Frans Bouma | Lead developer LLBLGen Pro
BlueCell avatar
BlueCell
User
Posts: 83
Joined: 12-Jul-2004
# Posted on: 06-Nov-2005 19:30:18   

Well, I must admit that I am far to puristic, as I am waisting to much time on thinking about the perfect design. IMO this is bad, very bad, but I don't know how to turn away my face from all that 'bad' code frowning (got some tips for me on how you do this?).

For example, I just can't pass along an EntityCollection as a parameter to a function of a class, because of the persistance logic inside it: it just doesn't belong in that class and the class should not be able to say save data (it should only read the data that it needs). And what makes it even more idiotic is that I am the only developer in the 'team'! So misuse of the class will never happen.

So what do I do? I try to create a similair object which only has the data it needs and then converting the EntityCollection to this object, just to make the object not violate any design rules.

And how do I create such an object? Well, I tried to use some kind of factory pattern. While this worked OK, I still have a creepy feeling about it. I think this is because of the misuse of the factory pattern: the class I created is just a class with one function with a EntityCollection, returning the object.

I even tried to use the adapter pattern: have you ever tried to make an adapter for a collection. Damn, what a work!

So both solutions didn't work. So I tried the last thing I could think of: loop throught the EntityCollection and for every Entity make the object and put it in a list.

So while I could just use the EntityCollection, I tried to come up with a better solution, but ended with ineffective solutions (well, except for the factory solution, which isn't really a factory, is it?).

So... should I just use the EntityCollection? Or should I perhaps still go for Adapter? Or what about using the factory solution (as it does work)?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39749
Joined: 17-Aug-2003
# Posted on: 06-Nov-2005 21:10:34   

BlueCell wrote:

Well, I must admit that I am far to puristic, as I am waisting to much time on thinking about the perfect design. IMO this is bad, very bad, but I don't know how to turn away my face from all that 'bad' code frowning (got some tips for me on how you do this?).

Sure, read 'from coder to developer' or 'the pragmatic programmer', or simply put common sense into gear. No-one will deny that in theory, lots of things make sense. However, in practise, a lot doesn't, or is simply not that useful. For example, every time someone tries to convince me that POCO is way better than entity classes derived from a common base class, I feel a bit hopeless. Not about what I thought and think is the 'best' way, but because I'm faced with someone who doesn't understand the idea behind pragmatism on one side and the limits a theory has in practise if you forget the theoretic boundaries set for the theory.

You use a couple of times the word 'bad' in your sentence. I'm pretty sure you can cough up reasons why it's bad. I am also pretty sure I can cough up reasons which make your reasons look not that smart, from ONE point of view (POV). That's simply because there are different POV on a given subject simple_smile , and the funny thing is that each POV is based on a different reasoning which, if I may say so, all make sense, but in their own universe of truth. I can perfectly understand why someone picks selfservicing and I can also perfectly understand why someone picks adapter, simply because there are different reasons to pick those, and if you prioritize differently, you end up on one side of the fence and not on the other side.

But above all: be pragmatic. Being pragmatic isn't bad, a sin or other evil. It's simply being pragmatic, i.e.: applying wisdom to the situation so you get the most advantage out of it. Because never forget: no-one will give you a promotion because your project is 3 months over due but that's because you thought some theory is better over the other. (to give an extreme example wink )

For example, I just can't pass along an EntityCollection as a parameter to a function of a class, because of the persistance logic inside it: it just doesn't belong in that class and the class should not be able to say save data (it should only read the data that it needs).

Why should it be able to read the data it needs but not save it? What if you need to use a BL tier to read data? Why is it in your eyes 'good' to place fetch logic into the collection but not save logic ? simple_smile Personally, I don't think that makes a lot of sense, no offence.

And what makes it even more idiotic is that I am the only developer in the 'team'! So misuse of the class will never happen.

Never say never wink . Everyone will once end up in the situation where a shortcut can save your @ss and doing it 'right' doesn't (besides the question: #define 'right' ). I've been there too, honestly. And even then, what will happen with the code once you moved on to another project and some trainee is ordered to 'get started with everything by adding some simple new feature'... ?

So what do I do? I try to create a similair object which only has the data it needs and then converting the EntityCollection to this object, just to make the object not violate any design rules.

That shouldn't be necessary. If you want to disable save logic in selfservicing, you can of course do that (it's not pretty, but it's doable). (generate into every entity an override of insertentity and updateentity, which do nothing, if you don't set a given value in a new property for example. )

I even tried to use the adapter pattern: have you ever tried to make an adapter for a collection. Damn, what a work!

What does that mean: an adapter for a collection? confused

So both solutions didn't work. So I tried the last thing I could think of: loop throught the EntityCollection and for every Entity make the object and put it in a list.

hmm, doesn't sound the way to go. But I've to admit, your requirements of having fetch logic in the collection but not save logic in the collection isn't quite what's offered by both patterns: selfservicing or adapter.

So while I could just use the EntityCollection, I tried to come up with a better solution, but ended with ineffective solutions (well, except for the factory solution, which isn't really a factory, is it?).

So... should I just use the EntityCollection? Or should I perhaps still go for Adapter? Or what about using the factory solution (as it does work)?

You should go for adapter and simply use a piece of logic in your BL which does your fetching. At least, that's IMHO what you should be doing. You can use EntityCollection as your data transfer object, work with the entities etc. in the PL tier, and when done, pass it on to the BL tier (or use a unit of work) and in there handle it further for persistence using your piece of logic which runs the business rules prior to saving.

Frans Bouma | Lead developer LLBLGen Pro
BlueCell avatar
BlueCell
User
Posts: 83
Joined: 12-Jul-2004
# Posted on: 06-Nov-2005 23:01:20   

Otis wrote:

Sure, read 'from coder to developer' or 'the pragmatic programmer', or simply put common sense into gear. No-one will deny that in theory, lots of things make sense. However, in practise, a lot doesn't, or is simply not that useful. For example, every time someone tries to convince me that POCO is way better than entity classes derived from a common base class, I feel a bit hopeless. Not about what I thought and think is the 'best' way, but because I'm faced with someone who doesn't understand the idea behind pragmatism on one side and the limits a theory has in practise if you forget the theoretic boundaries set for the theory.

You use a couple of times the word 'bad' in your sentence. I'm pretty sure you can cough up reasons why it's bad. I am also pretty sure I can cough up reasons which make your reasons look not that smart, from ONE point of view (POV). That's simply because there are different POV on a given subject simple_smile , and the funny thing is that each POV is based on a different reasoning which, if I may say so, all make sense, but in their own universe of truth. I can perfectly understand why someone picks selfservicing and I can also perfectly understand why someone picks adapter, simply because there are different reasons to pick those, and if you prioritize differently, you end up on one side of the fence and not on the other side.

But above all: be pragmatic. Being pragmatic isn't bad, a sin or other evil. It's simply being pragmatic, i.e.: applying wisdom to the situation so you get the most advantage out of it. Because never forget: no-one will give you a promotion because your project is 3 months over due but that's because you thought some theory is better over the other. (to give an extreme example wink )

There is much truth in there. Hopefully, I can adapt myself to have best of both worlds. Thank you for the inspiring words!

Why should it be able to read the data it needs but not save it? What if you need to use a BL tier to read data? Why is it in your eyes 'good' to place fetch logic into the collection but not save logic ? simple_smile Personally, I don't think that makes a lot of sense, no offence.

Uhm... what I ment was, that a specific class needs data and that I didn't want the class to use the llblgen collection, as this provides way more then only the data. So I was thinking about creating (by using the llblgen collection) an other collection which only provides data. I now see that I could just let the class use the llblgen collection.

What does that mean: an adapter for a collection? confused

Uh Gof Adapter pattern for a collection: I know, it sounds rediculious!

You should go for adapter and simply use a piece of logic in your BL which does your fetching. At least, that's IMHO what you should be doing. You can use EntityCollection as your data transfer object, work with the entities etc. in the PL tier, and when done, pass it on to the BL tier (or use a unit of work) and in there handle it further for persistence using your piece of logic which runs the business rules prior to saving.

Uh... to clarify: should I use adapter, because I think like persistence is a 'service', or because I need it, because I don't. When I began this project I am doing, I choose selfservicing because I don't have to use adapter and thus making it myself easier and develop faster. However, if I can force myself to be more pracmatic, isn't it so that I should go for selfservicing. Ofcours, that is if I want to develop faster and be practmatic! I could also choose to be more puristic and use adapter.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39749
Joined: 17-Aug-2003
# Posted on: 09-Nov-2005 10:57:49   

BlueCell wrote:

Otis wrote:

...

There is much truth in there. Hopefully, I can adapt myself to have best of both worlds. Thank you for the inspiring words!

No problem simple_smile

Why should it be able to read the data it needs but not save it? What if you need to use a BL tier to read data? Why is it in your eyes 'good' to place fetch logic into the collection but not save logic ? simple_smile Personally, I don't think that makes a lot of sense, no offence.

Uhm... what I ment was, that a specific class needs data and that I didn't want the class to use the llblgen collection, as this provides way more then only the data. So I was thinking about creating (by using the llblgen collection) an other collection which only provides data. I now see that I could just let the class use the llblgen collection.

Exactly, as that's really just a collection with some functionality you might need later on in a PL tier and/or with remoting/xml webservices/xml usage.

What does that mean: an adapter for a collection? confused

Uh Gof Adapter pattern for a collection: I know, it sounds rediculious!

Oh that adapter! simple_smile . I'll check it out, I haven't touched the book in a while.

You should go for adapter and simply use a piece of logic in your BL which does your fetching. At least, that's IMHO what you should be doing. You can use EntityCollection as your data transfer object, work with the entities etc. in the PL tier, and when done, pass it on to the BL tier (or use a unit of work) and in there handle it further for persistence using your piece of logic which runs the business rules prior to saving.

Uh... to clarify: should I use adapter, because I think like persistence is a 'service', or because I need it, because I don't. When I began this project I am doing, I choose selfservicing because I don't have to use adapter and thus making it myself easier and develop faster. However, if I can force myself to be more pracmatic, isn't it so that I should go for selfservicing. Ofcours, that is if I want to develop faster and be practmatic! I could also choose to be more puristic and use adapter.

hehe interesting POV simple_smile . The way I see 'pragmatic' in this context is that you should first prioritize what you need most and want to avoid most and then pick the pattern that fits those priorities, and the pragmatic part is in the fact that you then accept the mismatches between the picked pattern and your priority list and deal with them.

Frans Bouma | Lead developer LLBLGen Pro
BlueCell avatar
BlueCell
User
Posts: 83
Joined: 12-Jul-2004
# Posted on: 09-Nov-2005 16:02:50   

Thank you for answering my questions Frans. Great support, not only on LLBLGen, but as a programmer and therefore person aswell! I now see the pracmatic way, and I am slighty turning into a more pracmatic programmer (and person). I always thought, that being practmatic means not be look back at your code and just keep coding. This is not true, as most of the time, being pracmatic also means you should refactor (improve) your excisting code when it is needed.