|
| » myCSharp.de Diskussionsforum |
|
|
|
|
Autor
 |
|
JuyJuka
myCSharp.de-Poweruser/ Experte
Dabei seit: 30.11.2005
Beiträge: 2.187
Entwicklungsumgebung: VS2010 Herkunft: Deutschland
|
|
Ich bin nicht sicher, ob wir nicht zu weit vom eigentlichen Thema abschweifen. Ich werd eine Beispielklasse posten, wenn Ihr wollt. Dauert aber noch etwas.
|
|
11.11.2007 03:16
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
JuyJuka
myCSharp.de-Poweruser/ Experte
Dabei seit: 30.11.2005
Beiträge: 2.187
Entwicklungsumgebung: VS2010 Herkunft: Deutschland
Themenstarter
|
|
So, hier kommt eine kleine Beispiel-Klasse.
Im Moment muss man noch den genauen Typ kennen aber an dem Problem arbeite ich gerade.
Vielleicht sollten wir das hier in einen anderen Thread verschieben?
C#-Code: |
namespace Beispiel
{
[
Aisys.ReflectionVersion.Tabelle("transport")]
[
Aisys.ReflectionVersion.Protokolliert(true)]
[
Aisys.ReflectionVersion.AutoWert("id","transport")]
public class Transport : Aisys.AisysObject
{
#region Normale Attribute für die Daten, mit standard Werten
private decimal transportID = decimal.MinValue;
private Ort ziel = null;
private decimal zielID = decimal.MinValue;
private Ort quelle = null;
private decimal quelleID = decimal.MinValue;
private string zusatz = string.Empty;
private TransportStatus status = TransportStatus.Offen;
#endregion
[
Aisys.ReflectionVersion.Data("id")]
[
Aisys.ReflectionVersion.ID()]
public decimal TransportID
{
get { return this.transportID; }
private set { this.transportID = value; }
}
[
Aisys.ReflectionVersion.Data("zusatz")]
public string Zusatz
{
get { return this.zusatz??string.Empty; }
set { this.zusatz =value??string.Empty; }
}
[
Aisys.ReflectionVersion.Data("status")]
public TransportStatus Status
{
get { return this.status; }
private set { this.status = value; }
}
[
Aisys.ReflectionVersion.Refer("DBZiel")]
public Ort Ziel
{
get
{
if (this.zielID != decimal.MinValue && this.ziel == null)
{
Aisys.ExtendedSelect.Select<Ort> select = Aisys.ExtendedSelect.SelectFactory.Create<Ort>();
select.Objekt = new Ort(this.zielID);
select.Bedingung = new Aisys.ExtendedSelect.PropertyBedingung<Ort>(
"OrtID");
this.ziel = select.ExecuteAsForeigenKey();
}
return this.ziel;
}
set
{
this.ziel = value;
this.zielID = (value == null ? decimal.MinValue : value.OrtID);
}
}
[
Aisys.ReflectionVersion.Data("ziel")]
private decimal DBZiel
{
get { return this.zielID; }
set { this.zielID = value; }
}
[
Aisys.ReflectionVersion.Refer("DBQuelle")]
public Ort Quelle
{
get
{
if (this.quelleID != decimal.MinValue && this.quelle == null)
{
Aisys.ExtendedSelect.Select<Ort> select = Aisys.ExtendedSelect.SelectFactory.Create<Ort>();
select.Objekt = new Ort(this.quelleID);
select.Bedingung = new Aisys.ExtendedSelect.PropertyBedingung<Ort>(
"OrtID");
this.quelle = select.ExecuteAsForeigenKey();
}
return this.quelle;
}
set
{
this.quelle = value;
this.quelleID = (value == null ? decimal.MinValue : value.OrtID);
}
}
[
Aisys.ReflectionVersion.Data("quelle")]
private decimal DBQuelle
{
get { return this.quelleID; }
set { this.quelleID = value; }
}
public void Beginnen()
{
this.Status = TransportStatus.InArbeit;
this.Save();
}
public void Beenden()
{
this.Status = TransportStatus.Erledigt;
this.Save();
}
public void Stornieren()
{
Transport retoure = null;
if (this.Status == TransportStatus.Erledigt
|| this.Status == TransportStatus.InArbeit)
{
retoure = new Transport();
retoure.Ziel = this.Quelle;
retoure.Quelle = this.Ziel;
}
Aisys.AisysObject.SaveAsTransaction(this, retoure);
}
}
public enum TransportStatus
{
Offen,
InArbeit,
Erledigt,
Storniert
}
#region Ort
public class Ort : Aisys.AisysObject
{
public Ort() { }
public Ort(decimal id) { this.OrtID = id; }
public decimal OrtID
{
get { return decimal.MinValue; }
private set { }
}
}
#endregion
}
|
|
|
11.11.2007 05:06
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Rainbird
myCSharp.de-Poweruser/ Experte
Dabei seit: 28.05.2005
Beiträge: 3.716
Entwicklungsumgebung: Visual Studio 2010 Herkunft: Mauer
|
|
Diese Klassen kapseln den Datenzugriff objektorientiert. Du nennst sie aber "Business-Klassen" (vgl. typed oder untyped Dataset). Ich würde bei Business-Klassen vermuten, dass sie die Kern-Geschäftslogik enthalten. Wie sieht es mit Berechnungen etc. aus? Packst Du die auch direkt in diese Klassen?
|
|
12.11.2007 07:21
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
JuyJuka
myCSharp.de-Poweruser/ Experte
Dabei seit: 30.11.2005
Beiträge: 2.187
Entwicklungsumgebung: VS2010 Herkunft: Deutschland
Themenstarter
|
|
Wenn keine weiterführenden Anforderungen vorliegen, kommen Berechnungen und sowas auch in diese Klassen.
Meist wird aber noch Flexibilität oder Ähnliches verlangt, dann wende ich noch Patterns/Entwurfsmuster an (z.B. Statepattern, Templatepattern, ...). Dann wird die Geschäftslogik wieder ausgelagert.
Trotzdem Bilden immer diese Klassen die "Schnittstellen" für die UI (Ich weiß selber, dass hier Interfaces angesagt wären, aber an dem Problem arbeite ich gerade nocht.).
Ungefähr so:
C#-Code: |
public class Transport
{
private ITransporArt art;
public void Ausfuehren()
{
this.art.Ausfuehren(this);
}
}
|
Gruß
Juy Juka
|
|
12.11.2007 19:17
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Rainbird
myCSharp.de-Poweruser/ Experte
Dabei seit: 28.05.2005
Beiträge: 3.716
Entwicklungsumgebung: Visual Studio 2010 Herkunft: Mauer
|
|
Deine Klassen sind also alles in einem. Sie enthalten: - Definition der Datenstrukturen
- Datenzugriffslogik
- Geschäftslogik
Das erinnert mich spontan an die Objektmodelle von Word und Outlook. Ein durchgängiges Objektmodell. Nur sind Word und Outlook reine Desktop-Anwendungen (also 1-Tier). Auch Adobe Photoshop und Adobe InDesign haben Objektmodelle in der Art. Aber auch das sind reine Desktop-Anwendungen.
Kein Datenbank-Server, kein Applikations-Server. Einfach nur ein monolithischer Prozess.
Für reine Desktop-Anwendungen mag dieses Konzept super sein, aber nicht für mehrschichtige, verteilte Geschäftsanwendungen. Wenn alles in einer Klasse steht, kann man keine Schichten bilden und diese in verschiedenen Prozessen bzw. auf verschiedenen Computern laufen lassen. Selbst wenn Du sagst: "Eine Mittelschicht, die alles abdeckt, genügt mir!", hast Du ein Problem. Deine Business-Klassen skalieren nicht gut. Sie eignen sich deshalb nicht für den Betrieb auf einem Anwendungsserver. Grund dafür ist, dass sie statusbehaftet sind. Wenn ein Client z.B. zwei Angebote mit jeweils 10 Positionen bearbeitet, müssten auf dem Anwendungsserver 22 Objekte über die komplette Bearbeitungsdauer im Hauptspeicher gehalten werden. Wenn es 10 gleichzeitige Benutzer sind, die Angebote erfassen, wären das schon 220 Objekte. Die Server-Ressourcen würden damit geradezu verschwenderisch verpulvert und wären bereits bei wenigen gleichzeitigen Anwendern aufgebraucht. 2 Angebote mit 10 Positionen sind nur ein kleines Beispiel. Überlege mal, wie viele Objekte ein Sachbearbeiter wirklich den Tag über öffnet und bearbeitet. Die meiste Zeit sitzt er vor dem Monitor und schaut sich die Präsentation der Daten an. Nur innerhalb ein paar kurzer Klicks, werden wirklich Daten abgerufen und gespeichert. Trotzdem würden Deine statusbehafteten Business-Objekte die Ganze Zeit Server-Ressourcen verbrauchen. Stell Dir vor, es arbeiten 300 Benutzer gleichzeitig mit Deiner Anwendung. Wie groß müsste die Hardware des Applikations-Servers dimensioniert sein, damit alle flüssig arbeiten können, wenn es sich um eine 3-Tier Anwendung handelt?
Es ist alles andere als sinnvoll, Server-Ressourcen zu verschwenden. Man sollte Server-Ressourcen so kurz wie möglich (also z.B. nur genau in den 40ms, in denen wirklich Daten abgerufen oder gespeichert werden) reservieren und so schnell wie möglich wieder freigeben. Das ist aber nur mit statuslosen Geschäftsklassen und passiven DTOs (bzw. DataSets/DataTables) möglich.
Deshalb bin ich der Meinung, dass solche aktiven Objektmodelle, wie Du sie mit Deinen Business-Klassen aufbaust, gut für Desktop-Anwendungen wie Word oder Photoshop sind, aber für n-Schichtige und besonders verteilte Anwendungen völlig ungeeignet und sogar schädlich. Fat-Client und DB-Server ist das höchste er Gefühle, was diese Architektur verträgt. Wenn Du damit auf Dauer auskommst, sind die Objekte okay, wenn aber nicht, solltest Du Deine Architektur nochmal überdenken.
|
|
13.11.2007 07:53
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
FZelle
myCSharp.de-Poweruser/ Experte
Dabei seit: 23.04.2004
Beiträge: 8.525
|
|
Schon mal daran gedacht, das ein nicht unbeträchtlicher Teil der SW-Welt
i.M. eher auf Smartclient statt auf fette Appserver setzt?
Der Server als solcher ist da nur zur Datenhaltung gedacht, die vorhandene
Rechenleistung der Clients kann mit einfachen sachen wie OfflineDB's und co
genauso einfach skalieren, ohne das man hunderte Barrieren durchbrechen muss.
Wenn Du lieber mit einem Appserver arbeitest, deine Sache, der vernünftig gemachte SmartClient
kann die Aufgabe genauso erledigen.
Ist wie bei vielen Sachen in der SW-Entwicklung eine reine Frage der Anschauung.
|
|
13.11.2007 09:11
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Tokka
myCSharp.de-Mitglied
Dabei seit: 20.04.2005
Beiträge: 108
Entwicklungsumgebung: VS 2010 Herkunft: Hamburg
|
|
Hallo Zusammen,
ich finde Eure Diskussion sehr interessant. Die Anmerkungen von Rainbird sind für mich absolut nachvollziehbar. Skalierbarkeit ist ein sehr wichtiges Thema, welches eine sehr wichtige Rolle bei Geschäftsanwendungen einnimmt.
Ich selbst bin nur ein privat-Entwickler und beschäftige mich einfach aus Interesse mit der Umsetzung. Beruflich bin ich für das Management und Monitoring der Datenbank- und Applikationsserver zuständig. Anwendungen, die nicht oder nur schlecht skalieren, machen mir dabei häufig große Probleme, da die Last sehr schnell steigt.
Da hier im Forum die Diskussion bzw. Fragen zur Layer und Tier Entwicklung immer häufiger kommen, wäre es schön, wenn ein entsprechendes Beispiel mal vorliegen würde. Ja ich weiss, Rainbird hat das MVC-Beispiel gepostet, aber ich erkenne hier (vielleicht weil mir die Erfahrung / Kenntniss fehlt) die Zerlegung in Tiers nicht.
Die AdventureWorks Cinema Anwendung nutzt leider auch kein ADO.Net sondern typisierte Listen.
Es wäre also schön, mal ein Beispiel für eine echte n-Tier Anwendung zu haben. Ich selbst bin nicht in der Lage ein entsprechendes Beispiel zu erstellen, da mir die Erfahrung fehlt.
Gruß
Tokka
|
|
13.11.2007 09:50
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
xxxprod
myCSharp.de-Poweruser/ Experte
Dabei seit: 13.04.2006
Beiträge: 1.333
Entwicklungsumgebung: Visual Studio 2010 Herkunft: Österreich\Wien
|
|
Da schließ ich mich doch gleich mal an
Wenn einer der Tier-Profis ein Beispiel erstellen könnte, wäre das bestimmt für viele sehr hilf/lehrreich.
Lg XXX
|
|
13.11.2007 10:04
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Tokka
myCSharp.de-Mitglied
Dabei seit: 20.04.2005
Beiträge: 108
Entwicklungsumgebung: VS 2010 Herkunft: Hamburg
|
|
| Zitat: |
Original von Rainbird
Ich werde gerne ein Beispiel posten, aber das kann etwas dauern, da solche Beispiele schon etwas aufwändiger sind. Shließlich braucht eine 3-Tier-Anwendung eine gewisse Infrastruktur. Vor allem einen Applikationsserver. |
Gute Morgen Rainbird,
"Gut Ding will Weile haben!" dehalb sei Dir die Zeit gewährt, um uns Unwissende in die Untiefen der n-Tier architektur einzuführen
Freue mich schon auf Dein Beispiel.
Gruß
Tokka
|
|
14.11.2007 10:24
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
FZelle
myCSharp.de-Poweruser/ Experte
Dabei seit: 23.04.2004
Beiträge: 8.525
|
|
@Tokka:
Natürlich benutzt Adventureworks Cinema ADO.NET, anders geht in .NET der DB zugriff nicht.
@Rainbird:
Uuuuuh, Glaubenskriege.
Ich habe hier schon mehrfach geschrieben, das eine Enterpriseapp mit Appserver
deutlich besser und kostengünstiger skaliert als eine reine DB-Server basierte Anwendung.
Nur ab wann braucht man das?
Die wenigsten benötigen soetwas wirklich, und diese anderen fahren mit einem
durchdachten Smartclient deutlich besser.
|
|
14.11.2007 10:41
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
LastGentleman
myCSharp.de-Mitglied
Dabei seit: 13.03.2005
Beiträge: 1.272
Entwicklungsumgebung: VS 2012 Pro, MS Access Herkunft: Österreich
|
|
Hallo zusammen,
Smartclient's sind in der regel meist auch n-tier Anwendungen. Der Zugriff erfolgt meist über eine Webservice auf die Datenbank.
Verteilung der Tiers
1. SmartClient App -> Präsentations-Schicht
2. Webservice -> Übertragungs-Schicht
3. Business Logic -> Business Schicht
4. Data Access -> Datenzugriff Schicht
5. Database -> Datenbank
Wenn man nun es geschickt architektural anwendet und das System so aufbaut das man die Übertragungsschicht weglassen kann, so ist es auch für kleine Single User Anwendungen genauso geeignet wie für Enterprise Apps wo es über 3 gereicht wird.
Lg.
LastGentleman
|
|
14.11.2007 12:17
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
FZelle
myCSharp.de-Poweruser/ Experte
Dabei seit: 23.04.2004
Beiträge: 8.525
|
|
Richtig, wenn man SmartClients richtig aufbaut ( schon mit CAB und den Services gearbeitet? )
dann ist der Umstieg, wenn es dann nötig wird ziemlich simple.
Aber man benötigt nicht gleich am anfang den Appserver, kann ihn aber bei zeiten einfügen.
Das machen moderne System dann auch möglich ;-)
Wobei die Aufteilung dann eher so aussieht.
1. SmartClient App - > Gui auf MVP basis.
2. BusinessLogic -> Ist aufgeteilt in den Lokal Part in dem WorkItem ( UseCase kapselung)
und den Services.
3. Datenzugriff -> Services erledigen dies.
Bei CAB/SCSF lässt sich in einem WorkItem/UseCase nachträglich
jeder Service simplst austauschen, ohne neukompilierung, so kann man
mit einer Textdatenhaltung anfangen, dann auf eine Locale DB umschalten,
und ggf auch eine Remote oder Appserver Anbindung realisiern.
Auch die Teile der BL die als service implementiert sind sind einfachst zu tauschen.
So braucht man keine Spatzen wenn man kanonen, äh ne anders rum.
Aber man kann auch Perschings besorgen und benutzen.
|
|
14.11.2007 19:24
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
LastGentleman
myCSharp.de-Mitglied
Dabei seit: 13.03.2005
Beiträge: 1.272
Entwicklungsumgebung: VS 2012 Pro, MS Access Herkunft: Österreich
|
|
Hallo FZelle,
danke für deinen Kommentar, ich hab leider noch nicht viel mit CAB gemacht, ich schaue mir gerade sehr viel im Bereich Software Architektur an damit ich eine Solide Grundlage habe vorauf ich bauen kann.
Diesen Ansatz findet man ja schon in SOA wo alles nur Services und die Logik die dahinter liegt ausgetauscht werden kann.
Das schöne bei dem Ansatz mit CAB ist ja auch das es relativ Leicht ist die Zwischenschicht wie eine Datenbank oder eine Webservice einzufügen.
|
|
15.11.2007 07:48
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
mirkom76
myCSharp.de-Mitglied
Dabei seit: 14.11.2007
Beiträge: 110
Entwicklungsumgebung: Visual Studio 2008 Team Suite Herkunft: Deutschland
|
|
Hallo,
um eine solide Basis zu haben kann ich ein Buch empfehlen "Framework Design Guidelines". Da stehe viele Information zu einem vernünftigen Design drin. Vor allem sind viele Dinge sehr logisch, die aber in den meisten Unternehmen nicht angewendet werden. Da ich grundsätzlich beim Kunden vor Ort in den Projekten entwickel, denke ich, dass sich weiss wovon ich rede[:-)]
Man findet sich sehr schnell zurecht, wenn man bestimmte Regeln beachtet. Falls ein Unternehmen allerdings meint, gegen den Strom schwimmen zu müssen, braucht man sich nicht zu wundern, wenn neue Mitarbeiter lange Einarbeitungszeiten haben. Das ist meistens keine Sache der komplexität, sondern eher etwas der Architektur.
|
|
17.11.2007 20:08
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
| Zwischen diesen beiden Beiträgen liegt mehr als ein Monat. |
Rainbird
myCSharp.de-Poweruser/ Experte
Dabei seit: 28.05.2005
Beiträge: 3.716
Entwicklungsumgebung: Visual Studio 2010 Herkunft: Mauer
|
|
| Zitat von Rainbird: |
| Ich werde gerne ein Beispiel posten, aber das kann etwas dauern, da solche Beispiele schon etwas aufwändiger sind ... |
Das Beispiel-Projekt kommt gut voran (AppServer steht!).
Hier gibts die ersten Ergebnisse: .NET Applikationsserver
Edit:
Das Beispiel-Projekt ist jetzt lauffähig und kann unter obigem Link heruntergeladen werden.
Da dieser Thread hier der eigentliche Auslößer war, das Beispiel-Projekt zu machen und ich schon einige Abende dafür investiert habe, erwarte ich nun auch ein ausführliches Feedback.
|
|
20.12.2007 00:20
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
|