Ich habe in dieser Woche mein erstes Blender Beta Build erstellt für die Mac osx Umgebung. Ich bin kein Pro User unter Mac, aber ich musste feststellen das zum Beispiel der Mini Mac von Haus aus einfach zu bedienen ist. Selbst Anfänger haben es leicht sich schnell und sicher sich im X zu bewegen. Mir wurde aber auch bewusst wie stark die heutigen Linux Distributionen sind, vor ein paar Jahren war das noch anders. Wenn man heute die aktuelle Ubuntu Version anschaut, kann es mit guten Gewissen mithalten auf der Desktop Ebene. Sicher nicht in allen Punkten, es ist immer Abhängig wo man es einsetzt. Je nach Situation ist es eine gute alternative zu den gängigen Lösungen wie Windows oder Mac.
Warnung! Ich schweife vom Thema ab! – lol - Einer meiner Helden ist Sir Isaac Newton, er wurde zum Ritter geschlagen – Wie cool ist das den – ein Wissenschaftler in vielen Bereichen auch in der Mathematik. Einer seiner Hauptwerke ist sein Buch “Mathematische Principien der Naturlehre” – aus diesem Werk kommen die meisten bekannten Gesetzte die er entwickelt oder zusammengetragen hat. Ein Gesetzt basiert auf Aktion und Reaktion, das ganze ist sehr offen und ultra-vereinfacht dargestellt ohne wissenschaftliche Herleitung. Es ist auch nicht wichtig in diesem Zusammenhang wie genau das funktioniert, weil für uns ist das heute selbstverständlich (intuitiv, logisch). Newton hat das im Bereich Bewegung, Beschleunigung, Impuls und der Trägheit einer Masse entwickelt. Aber der Grundgedanke ist wahrscheinlich überall einsetzbar, ob es im Sozialen Umfeld ist oder bei einer Entscheidung im Management oder bei einem Wissenschaftlichen Effekt, einfach überall auch in der IT z.B Vor- und Nachteile eines Betriebssystem (Aktion und Reaktion)
Ich will damit sagen, man sollte offen bleiben für neue Ideen auch wenn man auf ein Produkt schwört. Rein-hören und etwas daraus lernen ist eine gute Sache. Darum ist mir erst jetzt bewusst geworden wie harmonisch Linux und Mac osx zusammen arbeiten. Mac osx , Linux und Unix haben sehr viele Gemeinsamkeiten. Der Aufwand um Informationen untereinander auszutauschen ist gleich null. Weil alle von Haus aus ein Tool und Hilfsmittel Set verwenden, die fast immer identisch sind. Zum Beispiel: ssh, ls, mkdir,mv , scp und viele mehr sind Grundbestandteile und funktionieren immer gleich. Im Punkt Sicherheit ist das Basis Setup ausreichend. Die Grundregel ist einfach, nicht mit dem Admin Konto seine tägliche Arbeit durchführen. Wenn man das einhält, ist man auf der sicheren Seite. Darum sind Desktop Firewall, Viren kein Thema. Das spart viel Aufwand -> also Zeit -> also Geld. Wo man in eine neue Strategie oder Forschung für das Unternehmen investieren kann.
Wann ist der Zeitpunkt sich darüber Gedanken zu machen eine neue IT Lösung zu suchen?
Ich finde zum Beispiel MS SharePoint, MS Office und das .NET Framework und auch Windows 7 sehr gute Produkte. C# ist so elegant und das Framework ist sauber strukturiert – ich liebe es^^. Leider werden diese Produkte sehr oft schlecht verwendet. Zum Beispiel: MS SharePoint wird oft in der Praxis als reiner File Share verwendet. Wo man die myProject Seiten erstellt, mit einem Wiki oder Blog wenn man Glück hat. Dort werden dann die ganzen Daten und Dokumente hoch-geladen. Dann nach einer gewissen Zeit werden es mehr Daten und dann kippt das Szenario. Weil plötzlich fängt man an nach Daten oder Dokumente zu suchen. Was schlecht ist und keinen Nutzen generiert für das Unternehmen. Aber MS SharePoint kann viel mehr, mit den Webparts und dem Workflow und Communication Tools aus dem Framework kann man ganze Business Prozesse Abbilden auf sehr elegante Art und Weise. Bei MS Office hat of das gleiche Problem, mir hat einmal ein Prof an der FH gesagt. Das die Anwender nur etwa 10% vom MS Office tatsächlich verwendet. Die neuen Konzepte werden meist gar nicht verwendet . Zum Beispiel: Meta/Tag Informationen setzten, wo für das finden hilfreich wäre. Der Nutzen von einer neuen Version ist sehr minimal oder gar nicht vorhanden. Wenn man an so einem Punkt erreicht. Dann sollte man die Fühler ausstrecken, egal auch welcher Plattform man arbeitet.
Als ich frisch angefangen habe mit OOP zu arbeiten, hatte ich sehr oft die Vererbung mehr bevorzugt als zum Beispiel Interfaces oder abstrakte Kassen. Ich konnte den Nutzen als Anfänger nicht wirklich sehen.
In diesem einfachen Beispiel möchte ich versuchen denn Nutzen von einem Interface einfach darzustellen. Interface oder Abstrakte Klassen helfen uns Regeln und eine Struktur in unsere Softwarelösung zu integrieren. Wenn wir ein Interface oder eine Abstrakte Klasse in unsere Klasse verwenden, müssen wir die Methoden Implementieren die vordefiniert sind. Wir sind also an eine Regel gebunden.
Das schöne daran ist, wir können diese Regeln aber auch erweitern und somit je nach Fall anpassen. Es ist eigentlich ein Spezialisierung von unserem Interface.
Zuerst erstellen wir ein Interface, in unserem Fall heisst die jetzt IAccount. Die sieht dann so aus:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ch.starwolf.tipp.Interface
{
interface IAccount
{
double Deposit { set;} // Einzahlung
double Payout { set;} // Auszahlung
double Balance { get;} // Saldo
int AccountID { set; get;} //Konto
int AccountOwner { set; get; } //Account Besitzer
void CalBalance(); // Berechnung des Saldos
}
}//end of namespace
In diesem Interface sind jetzt vier Eigenschaften und eine Methode definiert. Das ganze soll ein Regel für ein Konto darstellen. Es ist sehr vereinfacht Dargestellt. Wenn wir dieses Interface IAccount jetzt verwenden möchten in unserer Klasse, müssen wir alle Definitionen implementieren. In unserem Fall heisst die Klasse AccountBasic. Das sieht dann so aus:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ch.starwolf.tipp.Interface;
namespace ch.starwolf.tipp
{
class AccountBasic : IAccount
{
private double _deposit;
private double _payout;
private double _balance;
private int _accountID;
private int _accountOwner;
public AccountBasic() {
this._balance = 0;
}
public double Deposit {
set { _deposit = value;}
}// Einzahlung
public double Payout {
set { _payout = value; }
}// Auszahlung
public double Balance {
get { return _balance; }
}// Saldo
public int AccountID {
set { _accountID = value;}
get { return _accountID; }
}//Konto
public int AccountOwner {
set { _accountOwner = value; }
get { return _accountOwner; }
}//Account Besitzer
public void CalBalance() {
Console.WriteLine("Balance Methode von Accountbasic");
Console.WriteLine("Object : "+this.ToString());
Console.WriteLine(" ");
// Berechnung des Saldos
}
}//end of class
}//end of namespace
So haben wir es gelernt – nichts neues. Jetzt machen wir eine Spezialisierung von einem Interface, das ganze ist sehr einfach.
In unserem Beispiel möchten wir auch andere Konto Arten verwenden, die Ihre eigenen Berechnungen haben, aber trotzdem von der Art ein Konto sind. Zudem möchten wir eine Sicherheit haben, dass das neue Konto eine minimale Grund Regel aufweist. Wir verwenden sozusagen die Vererbung direkt auf dem neuem Interface. Wir könnten das ganze auch direkt auf einer Klasse machen.
Ich finde aber diese Variante sehr elegant und ist bei einer Anpassung Zentraler geregelt. Es hilft auch die Abhängigkeiten untereinander einfacher zu lesen. Das neue Interface heisst jetzt IAccountStock und ist eine Spezialisierung von IAccount. Das ganze sieht so aus:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ch.starwolf.tipp.Interface
{
interface IAccountStock : IAccount
{
int ShareNumber {set; get;} // Anzahl
string ShareSymbol {set; get;} // Symbol Aktie
void CalBuy(); //Berechnung Kauf
}
}
Das ganze ist wider sehr einfach gehalten – hoffe ich ^^ .
Wenn wir jetzt das neue Interface IAccountStock verwenden möchten für eine neue Klasse, müssen wir alle Methoden von IAccount Implementieren (die Basis Regel) . Zusätzlich müssen wir auch jetzt die zwei Eigenschaften und die Methode aus der Spezialisierung Implementieren.
In unserem Beispiel sieht das ganze so aus für die Klasse AccountStock:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ch.starwolf.tipp.Interface;
namespace ch.starwolf.tipp
{
class AccountStock : IAccountStock
{
private double _deposit;
private double _payout;
private double _balance;
private int _accountID;
private int _accountOwner;
private int _shareNunber;
private string _shareSymbol;
public AccountStock() {
this._balance = 0;
}
#region IAccount implementation
public double Deposit {
set { _deposit = value;}
}// Einzahlung
public double Payout {
set { _payout = value; }
}// Auszahlung
public double Balance {
get { return _balance; }
}// Saldo
public int AccountID {
set { _accountID = value;}
get { return _accountID; }
}//Konto
public int AccountOwner {
set { _accountOwner = value; }
get { return _accountOwner; }
}//Account Besitzer
public void CalBalance() {
Console.WriteLine("Balance Methode von AccountStock");
Console.WriteLine("Object : " + this.ToString());
Console.WriteLine(" ");
//Berechnung des Saldos
}
#endregion
#region IAccountStock implementation
public int ShareNumber {
set {_shareNunber = value;}
get{return _shareNunber;}
} // Anzahl
public string ShareSymbol {
set{_shareSymbol = value;}
get{ return _shareSymbol;}
} // Symbol Aktie
public void CalBuy()
{
Console.WriteLine("Buy Methode von AccountStock");
Console.WriteLine("Object : " + this.ToString());
Console.WriteLine(" ");
//Berechnung Kauf
}
#endregion
}//end of class
}//end of namespace
Ich hab dazu noch ein kleines Programm gemacht um zu zeigen wie die Regeln greifen. Das Programm ist sehr einfach aufgebaut.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ch.starwolf.tipp.Interface;
namespace ch.starwolf.tipp
{
class Program
{
static void Main(string[] args) {
Program oProgram = new Program();
AccountStock oStock = new AccountStock();
AccountBasic oBasic = new AccountBasic();
oProgram.ShowAccount(oStock);
oProgram.ShowAccount(oBasic);
oProgram.ShowStockmarket(oStock);
Console.ReadLine();
}
private void ShowStockmarket(IAccountStock param) {
param.CalBuy();
}
private void ShowAccount(IAccount param) {
param.CalBalance();
}
}//end of class
}//end of namespace
Hier sehen wir auch das wir die Programm Methoden ShowStockmarket und ShowAccount ein Interface Type erwarten. Das ganze hat den Vorteil einer losen Kopplung. Was in der OOP Welt immer gut ist, um Stare Strukturen in unserer Software zu vermeiden.
Wir müssen also nicht eine spezifisches Objekt übergeben sondern ein Objekt wo eine Implementation vom gewünschten Interface besitzt.
Das schöne an der ganzen Sache ist, das die individuelle Berechnung wo wir in der Klasse definiert haben verwendet wird. In der Methode ShowAccount wird die Methode CalBalance ausgeführt. Die CalBalance verwendet immer die Implementierte Methode von der eigenen Klasse. Man sieht das schön im Output:
Output Interface Example
So können wir also auf einfache Art sehr elegante Strukturen bauen. Die Regeln helfen uns eine Konsistenz in der Software zu erhalten. Zudem haben wir gesehen es förder auch die lose Kopplung in unserer Software. Das ganze ist sehr einfach gehalten und als Tipp gedacht. Alle Arten von Lösungen haben Ihre Vor- oder Nachteile, bis jetzt war dieser Ansatz bei mir immer Hilfreich und sollte einfach zeigen wie man mit Interfaces arbeiten kann.
Das Beispiel habe ich mit Visual Studio 2010 Express erstellt – das kleine Projekt könnt hier herunterladen: Interface001
Ich hab in meinem letzten Beitrag über Basis Regeln beim Software-Design berichtet. In diesem Beispiel versuche ich zu zeigen wie man mit einer Objektkomposition eine elegante Lösung baut. Das ganze kommt aus der Praxis und ist eine Debug/Log Lösung. Ich hab das ganze sehr vereinfacht um euch die Idee und den Grund Gedanken zu zeigen. Wie man so was lösen könnte.
Ausgangslage:
Die Softwarelösung war zu diesem Zeitpunkt sehr instabil. Ich wurde eingestellt die Softwarelösung zu Supporten und zu verbessern. Ein Hauptproblem war die Performance bei den wichtigen Prozessen vom Unternehmen (Bussiness Logik). Die Entwickler hatten begonnen überall im Code Prints Anweisungen einzubauen weil die Softwarelösung in der Prod Umgebung sich auch anders verhalten hatte. Es wurde sogar so extrem das die lieben Leute durch das ständige rein und raus kopieren von diesen Debug Prints auch ungewollt Fehler machten. Das ganze war eine Intranet Weblösung und die wurde aktiv 24h verwendet. Zudem Stand das ganze in einer Hight Secure Zone vom Unternehmen, man hatte keinen direkten Zugang zu dieser Zone.
Im Team Meeting hatte ich den Vorschlag gemacht eine Debug Lösung einzubauen. Wo man Ein- und Ausschalten kann über das Webinterface. Das ganze ist unabhängig und erweiterbar zudem wird das ganze nur in den kritischen Bereichen ergänzt.
Was brauchen wir?
Ein Interface in unserem Fall heisst es IDebug wo uns die Grund-Struktur für unsere Methode liefert.
Eine Klasse wo die Arbeit übernimmt und die Debug Informationen abarbeitet. Zudem ist der Aufbau dieser Klasse vom Interface IDebug abhängig.
Eine Methode in einer Bussiness Logik Klasse, in unserem Beispiel heisst die Klasse CurrencyBroker,
wo uns zeigt wie wir unsere Debug Lösung einbauen können. Das Interface liefert uns wider die Grundstrucktur.
Ich fange mit dem Interface an IDebug. Wo ganz einfach aufgebaut ist mit der Methode Debug. Wo als Argument einen string erwartet.
/**
* Interface Debug System
* */
using System;
namespace ch.starwolf.SoftwareDesign {
public interface IDebug {
void Debug(string arg);
}
}
Jetzt werden wir unsere Arbeiter Klasse definieren mit dem Klassennamen DebugLogger und der Implementation vom Interface IDebug. Ich habe weiter oben erwähnt das dass ganze erweiterbar ist. Wir sind genau an dieser Position jetzt, in unserm Beispiel wird unsere Klasse nur einen Output in die Konsole schreiben. Aber hier könnten wir weitere Klassen definieren wo zum Beispiel die Debug Informationen in eine Datenbank oder in ein XML schreibt. Wir könnten auch Klassen zusätzlich definieren wo uns ein Email zustellt oder ein RSS Feed abfüllt. Die Möglichkeiten sind fast unbegrenzt.
/**
* Debug job, write a log file
* */
using System;
namespace ch.starwolf.SoftwareDesign {
public class DebugLogger : IDebug{
public DebugLogger() {}
public void Debug(string Msg){
Console.WriteLine("Write Msg into a log file, Msg is : "+ Msg +DateTime.Now.ToString());
}
}//end of class
}
Jetzt kommt die Implementation in unsere Business Logik. Wir müssen nur eine Debug Methode definieren und beim Initialisieren ein IDebug Instanz durch-reichen. Die im Konstruktor von der Klasse mitgegeben wird. Die Business Logik hat somit nur mit ihren eigenen Instanzen zu arbeiten und ist nicht verantwortlich für das erstellen eines Debugger Objekts. Das ganze wir auch als Lose-Kopplung bezeichnet. Die Trennung ist dadurch klarer was nur Vorteile bringt. Das ist der ganze Aufwand um einen Debugger einzubauen, zudem bleibt die Implementation immer gleich auch für andere Business Logik Klassen. Das ganze sieht dann so aus.
/**
* critical Business logic
* */
using System;
namespace ch.starwolf.SoftwareDesign {
public class CurrencyBroker {
protected IDebug debugger;
public CurrencyBroker(IDebug debugger) {
this.debugger = debugger;
}
public void CurrencySale (string CC, int CCCount, int ID){
//do something
this.Debug("ID="+ID+" - CurrencySale - Done And Ready - ");
}
/* Debug Implementation */
protected void Debug(string Msg){
// if null no need for debug
if (this.debugger != null) {
this.debugger.Debug(Msg);
}
}
}//end of class
}
Der Aufruf und die Übergabe sieht so aus in unserem kleinen Beispiel.
/**
* Demo API
* */
using System;
using ch.starwolf.SoftwareDesign;
namespace ch.starwolf.SoftwareDesign {
class MainClass {
public static void Main(string[] args) {
Console.WriteLine("Run CurrencyBroker Job");
DebugLogger Debug = new DebugLogger();
CurrencyBroker job01 = new CurrencyBroker(Debug);
job01.CurrencySale("CHF",100,1);
}
}//end of class
}
Ausgabe der Konsole:
Run CurrencyBroker Job
Write Msg into a log file, Msg is : ID=1 - CurrencySale - Done And Ready - 23.03.2010 19:34:30
Dazu noch ein UML Diagramm. Die roten Felder könnten zusätzliche Klassen sein.
UML Diagramm
Ich hab das Beispiel mit MonoDevelop und das Diagramm mit Dia unter Linux erstellt. Das kleine Projekt könnt Ihr hier runter laden.
Das war der ganze Zauber zu diesem Thema. Viel Spass beim Ausprobieren @all.