C# - How to Detect a Windows Shutdown/Logoff and Cancel That Action (After Asking the User)

“Do not use Abstract Base class in Design; but in Modeling/Analysis”

It sounds like you are trying to use SOA to remotely access your object model. You would be better of looking at the interactions and capabilities you want your service to expose and avoid exposing inheritance details of your services implementation.

So in this instance where you need a list of user accounts your interface would look something like

[ServiceContract]
interface ISomeService
{
[OperationContract]
Collection<AccountSummary> ListAccountsForUser(
User user /*This information could be out of band in a claim*/);
}

[DataContract]
class AccountSummary
{
[DataMember]
public string AccountNumber {get;set;}
[DataMember]
public string AccountType {get;set;}
//Other account summary information
}

if you do decide to go down the inheritance route, you can use the KnownType attribute, but be aware that this will add some type information into the message being sent across the wire which may limit your interoperability in some cases.

Update:

I was a bit limited for time earlier when I answered, so I'll try and elaborate on why I prefer this style.

I would not advise exposing your OOAD via DTOs in a seperate layer this usually leads to a bloated interface where you pass around a lot of data that isn't used and religously map it into and out of what is essentially a copy of your domain model with all the logic deleted, and I just don't see the value. I usually design my service layer around the operations that it exposes and I use DTOs for the definition of the service interactions.

Using DTOs based on exposed operations and not on the domain model helps keep the service encapsulation and reduces coupling to the domain model. By not exposing my domain model, I don't have to make any compromises on field visibility or inheritance for the sake of serialization.

for example if I was exposing a Transfer method from one account to another the service interface would look something like this:

[ServiceContract]
interface ISomeService
{
[OperationContract]
TransferResult Transfer(TransferRequest request);
}

[DataContract]
class TransferRequest
{
[DataMember]
public string FromAccountNumber {get;set;}
[DataMember]
public string ToAccountNumber {get;set;}
[DataMember]
public Money Amount {get;set;}
}

class SomeService : ISomeService
{
TransferResult Transfer(TransferRequest request)
{
//Check parameters...omitted for clarity
var from = repository.Load<Account>(request.FromAccountNumber);
//Assert that the caller is authorised to request transfer on this account
var to = repository.Load<Account>(request.ToAccountNumber);
from.Transfer(to, request.Amount);
//Build an appropriate response (or fault)
}
}

now from this interface it is very clear to the conusmer what the required data to call this operation is. If I implemented this as

[ServiceContract]
interface ISomeService
{
[OperationContract]
TransferResult Transfer(AccountDto from, AccountDto to, MoneyDto dto);
}

and AccountDto is a copy of the fields in account, as a consumer, which fields should I populate? All of them? If a new property is added to support a new operation, all users of all operations can now see this property. WCF allows me to mark this property as non mandatory so that I don't break all of my other clients, but if it is mandatory to the new operation the client will only find out when they call the operation.

Worse, as the service implementer, what happens if they have provided me with a current balance? should I trust it?

The general rule here is to ask who owns the data, the client or the service? If the client owns it, then it can pass it to the service and after doing some basic checks, the service can use it. If the service owns it, the client should only pass enough information for the service to retrieve what it needs. This allows the service to maintain the consistency of the data that it owns.

In this example, the service owns the account information and the key to locate it is an account number. While the service may validate the amount (is positive, supported currency etc.) this is owned by the client and therefore we expect all fields on the DTO to be populated.

In summary, I have seen it done all 3 ways, but designing DTOs around specific operations has been by far the most successful both from service and consumer implementations. It allows operations to evolve independently and is very explicit about what is expected by the service and what will be returned to the client.

Reasons not to use abstract class instead of interface?

Only thing that you should be aware and make a conscious decision is a class can inherit from only one class but implement many interfaces.


Apart from that, some recommendations on using Abstract classes or Interfaces:

  • If you anticipate creating multiple versions of your component, create an
    abstract class. Abstract classes
    provide a simple and easy way to
    version your components. By updating
    the base class, all inheriting classes
    are automatically updated with the
    change. Interfaces, on the other hand,
    cannot be changed once created. If a
    new version of an interface is
    required, you must create a whole new
    interface.
  • If the functionality you are creating will be useful across a wide
    range of disparate objects, use an
    interface. Abstract classes should be
    used primarily for objects that are
    closely related, whereas interfaces
    are best suited for providing common
    functionality to unrelated classes.
  • If you are designing small, concise bits of functionality, use
    interfaces. If you are designing large
    functional units, use an abstract
    class.
  • If you want to provide common, implemented functionality among all
    implementations of your component, use
    an abstract class. Abstract classes
    allow you to partially implement your
    class, whereas interfaces contain no
    implementation for any members.

http://msdn.microsoft.com/en-us/library/scsyfw1d%28vs.71%29.aspx

Personally, I feel these recommendations are spot on. Especially Interfaces, on the other hand, cannot be changed once created. If a new version of an interface is required, you must create a whole new interface. is a very important point.

Patterns for Compensating Lack of Inheritance in SOA

No matter whether or not you think about SOA as implemented by SOAP, REST or messaging, services are document-centric. Services are not object-oriented.

While polymorphism is a strong design tool in OOD, it's not applicable in SOA because SOA modeling doesn't involve classes.

Patterns for Compensating Lack of Inheritance in SOA

No matter whether or not you think about SOA as implemented by SOAP, REST or messaging, services are document-centric. Services are not object-oriented.

While polymorphism is a strong design tool in OOD, it's not applicable in SOA because SOA modeling doesn't involve classes.

Interface vs Base class


Let's take your example of a Dog and a Cat class, and let's illustrate using C#:

Both a dog and a cat are animals, specifically, quadruped mammals (animals are waaay too general). Let us assume that you have an abstract class Mammal, for both of them:

public abstract class Mammal

This base class will probably have default methods such as:

  • Feed
  • Mate

All of which are behavior that have more or less the same implementation between either species. To define this you will have:

public class Dog : Mammal
public class Cat : Mammal

Now let's suppose there are other mammals, which we will usually see in a zoo:

public class Giraffe : Mammal
public class Rhinoceros : Mammal
public class Hippopotamus : Mammal

This will still be valid because at the core of the functionality Feed() and Mate() will still be the same.

However, giraffes, rhinoceros, and hippos are not exactly animals that you can make pets out of. That's where an interface will be useful:

public interface IPettable
{
IList<Trick> Tricks{get; set;}
void Bathe();
void Train(Trick t);
}

The implementation for the above contract will not be the same between a cat and dog; putting their implementations in an abstract class to inherit will be a bad idea.

Your Dog and Cat definitions should now look like:

public class Dog : Mammal, IPettable
public class Cat : Mammal, IPettable

Theoretically you can override them from a higher base class, but essentially an interface allows you to add on only the things you need into a class without the need for inheritance.

Consequently, because you can usually only inherit from one abstract class (in most statically typed OO languages that is... exceptions include C++) but be able to implement multiple interfaces, it allows you to construct objects in a strictly as required basis.

Interfaces and abstract classes for model classes (MVVM)

In the model-view-viewmodel design, most of the domain specific logic and behaviour actually ends up in the model. This is called the domain model in domain-driven-design.

That domain code might be reused in several deployment units/applications/services in your business, so they are independent of the actual WPF application you are writing.

The viewmodel serves as the testable application-specific adapter and mediator for the view you are just writing so that

  • the domain is not polluted with behaviour that is not needed across all applications
  • the domain is not polluted with state (fields, properties) that are just relevant for the given screen or UI (presentation state)
  • the view does not contain behaviour that you want to unit-test

Adding a parent class between models.Model and my Model classes

You can use Abstract Base Classes for that.

class MyModel(models.Model):
summary_table_headers = []
# define above methods in this base class
class Meta:
abstract = True

More info here.

Where should I place variables or methods needed by several (but not all) child classes?

When only a sub-set of sub-classes share functionality, this can be expressed with an interface that contains the methods in question, which is only implemented by the sub-classes that need them.

public interface OnOffable  {
boolean isOn();
void toggleOnOff();
void turnOn(boolean is_on);
void turnOn();
void turnOff();
}

class Switch extends Device implements OnOffable...

If one or more of the functions is moderately complicated, you can create a static utility function that helps prevent redundant code. In this example, however, the "complicated-ness" is the need to keep the on-off state.

In this situation, you can create an OnOffableComposer which (my preference) does not implement OnOffable.

And actually, since this particular interface can be completely implemented (meaning it needs no protected or abstract function), it can actually be a "simple" implementation of it:

public class SimpleOnOffable implements OnOffable  {
private boolean isOn;
public class OnOffableComposer(boolean is_on) {
turnOn(is_on);
}
public boolean isOn() {
return isOn;
}
public void turnOn(boolean is_on) {
isOn = is_on;
}
public void toggleOnOff() {
turnOn(!isOn());
}
public void turnOn() {
turnOn(true);
}
public void turnOff() {
turnOn(false);
}
}

Here's how it's used:

public class Switch extends Device implements OnOffable  {
private final SimpleOnOffable smplOnOff;
public Switch(boolean is_on) {
smplOnOff = new SimpleOnOffable(is_on);
}
public boolean isOn() {
return smplOnOff.isOn();
}
public void turnOn(boolean is_on) {
smplOnOff.turnOn(is_on);
}
public void toggleOnOff() {
smplOnOff.toggleOnOff();
}
public void turnOn() {
smplOnOff.turnOn();
}
public void turnOff() {
smplOnOff.turnOff();
}
}

Although the composer is "simple", this all demonstrates the concept of choosing composition over inheritance. It allows for much more complicated designs than single inheritance allows.



Related Topics



Leave a reply



Submit