Think First Development

Erst denken, dann programmieren

Durchsuche Beiträge in Allgemeines

Das Html-Helper Object des MVC2 Frameworks unterstützt kein Generieren von File-Input Steuerelementen. Hier ist ein Workaround für dieses Problem: Man überschreibt das Type-Attribut mit “file”.

<%: Html.TextBoxFor(model => model.File, new { size = "30", type = "file" }) %>

weiter lesen

Serverseitige Validierung

Das ASP.NET MVC2 Framework biete eine einfache Möglichkeit zur Validierung eines Modells: Data Annotations. Mit Attributen wird die Validierung für das Modell definiert. Im MVC2 Framework sind vier Validatoren enthalten: Required, StringLength, Range und RegularExpression. weiter lesen

6:15 Der Wecker hat klingelt. Die Nacht war viel zu kurz. Einen Kaffee trinken und pünktlich aus dem Haus, damit ich rechtzeitig da bin. Wollte mit dem Auto fahren und nicht in den Berufsverkehr kommen.

8:15 Mist! Viel zu spät losgefahren und in den Berufsverkehr geraten. Gehofft, dass alles noch klappt und es noch Frühstück gibt. Die Uhr rennt, der Verkehr steht.

9:25 Endlich da. Alle Parkplätze am Hotel waren leider besetzt. Also in Köln einen Parkplatz gesucht und zum Glück einen in der Nähe gefunden! Zeit für ein kleines Frühstück gehabt und die ersten bekannten Gesichter (wieder)gesehen wie Jan Welker und Gregor Biswanger. Besonders interessant waren die Gesichter hinter den Blogs die ich nur von Fotos kannte wie Thorsten Hans, Philip Proplesch und Gordon Breuer.

9:45 Begrüßung und Keynote durch die Organisatoren Roland Weigelt, Albert Weinert und Stefan Lange. Leider war der Raum viel zu voll um noch einen Platz zu ergattern. Also weiter gefrühstückt und gequatscht, dieses mal unter anderem mit Rainer Stropek über TimeCockpit und Windows Azure.

10:25 Der erste Vortrag beginnt: “Give Your Application a Triple Boost with Windows 7, Microsoft .NET 4.0, and Intel Multi-core” vom Rami Radi. Es ging nicht wie von mir erwartet um Windows 7 Applikationen und Multi-core Entwicklung sondern um Prozessorarchitektur und Auswirkungen auf den Entwickler. War man offen für dieses Thema, war der Vortrag sehr interessant und informativ. Besonders die Tick-Tock Vorgehensweise von Intel ist auch auf andere Projekte anwendbar und hat einen Hauch von “Red, Green, Refactor”.

11:40 Nicht nur draußen sondern auch im zweiten Vortrag war der Himmel blau…Azure-Blau. Rainer Stropek hat einen schönen Vortrag über die Migration einer lokalen Webapplikation in die Cloud gehalten. Dabei durften die Herausforderungen wie Datenbank und Dateisystem nicht fehlen. Pünktlich nach einer Stunde war die Applikation in der Cloud und lief.

12:55 Den dritten Vortrag habe ich sozusagen geschwänzt. Ich hätte sehr gerne den Vortrag von Oliver Sturm (Funktionale Programmierung in C#) oder von Thorsten Hans (MSBuild) gehört.Ich habe mich allerdings in den Sprecherraum zurückgezogen und bin noch einmal meine Präsentation durchgegangen.

13:55 Das Essen sah sehr lecker aus. Leider war mir der Andrang zu groß, also habe ich mich in die Sonne gelegt und abgewartet. Als ich mir dann die Mühe gemacht habe, Essen zu gehen war nur noch Nachtisch da. Als ich schließlich vom ganzen süßen Zeug satt war wurde neues Essen aufgelegt. Leider zu spät aber es war reichlich Essen da.

15:00 Es war endlich so weit, mein ASP.NET MVC2 Vortrag. Leider habe ich nur einen Teil von dem gezeigt, was ich zeigen wollte. 60 Minuten gingen viel zu schnell vorbei und habe mich viel zu lange an den Grundlagen aufgehalten. Es war viel zu wenig von den neuen tollen Features in ASP.NET MVC2.

16:15 Danach ging es dann zur “Konkurrenz”: ASP.NET 4.0 WebForms von Jan Welker. Es gab einen schönen Überblick über die neuen Features von ASP.NET 4.0. Die Beispiele waren sehr interessant und aufschlussreich. Sogar für mich als nicht WebForms Entwickler, da ASP.NET MVC2 auf WebForms aufsetzt.

17:30 Zu guter letzt ging es in den Vortrag “Warum sie JavaScript hassen sollten” “Warum sie nach diesem Vortrag JavaScript nicht mehr hassen können” von Andrè Krämer. Ich bin bekennender JavaScript verweigerer. Aber jQuery im Gegensatz dazu ist wieder schön und sogar ich kann dem inzwischen etwas abgewinnen. Keine Browser-Abfragen, kleine Helfer mit großer Auswirkungen und besonders das nachträgliche dynamisieren der (MVC)WebApplikation. Vielleicht hat Andrè aus mir einen jQuery Freund gemacht…wir werden sehen.

18:40 An der Verlosung habe ich als fauler Sprecher nicht teilgenommen. Für mich gab es nix zu gewinnen und so hatte ich Zeit für ein paar ruhige Gespräche abseits des Rahmenprogramms mit anderen Faulpelzen. Ich hatte auch ohne Feedbackbogen noch eine Tasse ergattert und das reicht als Preis ;) . Einen großen Dank an die nette Tassen-Dame.

19:00 Endlich die Grillfete. Lange hinausgeschoben, lange angekündigt und endlich war es so weit. Ein riesen Dank an Jan Welker und die aktiven Mitglieder des dotnet Forums. Das Essen war lecker, das Wetter super und die Teilnehmer allesamt nett.

21:30 Der Tag war lang, die Nacht war kurz. Noch einen Strauß Blumen für meine Frau gekauft, die mich seit Wochen nur noch vor dem Notebook sitzen sah und nicht viel von mit hatte. Glotze an, Augen zu.

Ich freue mich schon jetzt auf die dotnet Cologne 2011 und vielleicht wieder als Sprecher. Noch einmal einen riesigen Dank an die Organisatoren und Helfer der dotnet Cologne 2010.

Nach langer Zeit habe ich mit endlich die Zeit genommen und meine CD-Kiste aufgeräumt. Gefühlte 1000 CDs mit Linux Distrubutionen aus der Ausbildung, PC-Backups aus der Jahrtausendwende, Fotos und natürlich Daten Backups. Darunter waren auch 3 CDs mit Software aus vergangenen Tagen. Und so kann ich endlich auch Quellcode und Software (!) von vor über 10 Jahren präsentieren.

Mastermind

Das Spiel Mastermind hat mich eine Zeit begleitet. Der erste Anlauf mit Turbo Pascal hatte geschätzt 500 Zeilen Code um die Eingabe zu validieren und das Ergebnis zu präsentieren. Später habe ich dann mit VB 3 eine neue Version mit Control-Arrays und viel schlankerem Validierungscode geschieben, ca. 30 Zeilen. Leider konnte ich den SourceCode nicht finden, aber dafür könnt ihr hier das Programm herunterladen (incl. vbrun300.dll).

Client-Server-Chat

Das bis dahin größte Projekt war eine Client Server Applikation. Geschrieben habe ich das Programm mit Delphi 3, eine sehr lange Heimat für meine Programmierung. Mit Delphi habe ich die ersten multithreaded Applikationen entwickelt, Datenbankapplikationen geschrieben und Client Server Applikationen gebaut.
Das geniale an diesem Projekt war nicht der Chat, der über eine WinSock Client-Server TCP Verbindung statt fand sondern das “Malbrett”. Mit dieser Zeichenfläche konnten mehrere Benutzer an einem Bild malen. Falls jemand an dem Programm interessiert ist, könnt ihr die Sourcen und das Setup hier herunterladen.

Screenshots des IntraChat

Screenshots des IntraChat

Hier ist noch ein bißchen Turbo Pascal Code. Ich habe mal den Code des “Malfensters” eingefügt. Man sieht, dass die Kommunikation über ein WinSock Control funktioniert.


unit uniMalen;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, Buttons, ExtCtrls, StdCtrls, Spin, ColorGrd;

type TMalen = class(TObject)
            x1, x2, y1, y2, Dicke: Integer;
            Farbe: TColor;
            Werkzeug: Char;
            Absender: ShortString;
     end;
type
  TfrmMalen = class(TForm)
    imgPapier: TImage;
    MainMenu1: TMainMenu;
    Fenster1: TMenuItem;
    Schliessen1: TMenuItem;
    spbRectangle: TSpeedButton;
    spbEllipse: TSpeedButton;
    speWidth: TSpinEdit;
    Label1: TLabel;
    cdbColor: TColorDialog;
    ShapeColor: TShape;
    Label2: TLabel;
    spbLine: TSpeedButton;
    N1: TMenuItem;
    Neu1: TMenuItem;
    spbPixel: TSpeedButton;
    tmrPuffer: TTimer;
    procedure Schliessen1Click(Sender: TObject);
    procedure imgPapierMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure imgPapierMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure GetPaint(text: ShortString);
    procedure Send(Text: ShortString);
    procedure imgPapierMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ShapeColorMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure tmrPufferTimer(Sender: TObject);
    procedure Neu1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

procedure SendToPuffer(MyWerkzeug: Char);

var
  frmMalen: TfrmMalen;
  Startx, Starty, Currentx, Currenty: Integer;
  LMBGedruckt, MMBGedruckt, RMBGedruckt: Boolean;
  MPuffer: TList;
  Malen: TMalen;

implementation

uses uniMain;

{$R *.DFM}

procedure SendToPuffer(MyWerkzeug: Char);
// var text: String;
begin
        with Malen do begin
             x1 := Startx;
             y1 := Starty;
             x2 := Currentx;
             y2 := Currenty;
             Dicke := frmMalen.SpeWidth.Value;
             Farbe := frmMalen.ShapeColor.Brush.Color;
             Werkzeug := MyWerkzeug;
             Absender := frmMain.csoClient.Socket.LocalHost;
        end;
        MPuffer.Add(Malen);

{     Text := '%p%' + Malen.Werkzeug + '%' + IntToStr(Malen.x1) + '%' + IntToStr(Malen.y1) + '%' + IntToStr(Malen.x2) + '%' + IntToStr(Malen.y2) + '%' + IntToStr(Malen.Dicke) + '%';
     Text := Text + ColorToString(Malen.Farbe) + '%' + Malen.Absender + '%';
     frmMalen.Send(Text);
}end;

procedure TfrmMalen.Send(Text: ShortString);
begin
     frmMain.csoClient.Socket.SendText(Text);
end;

procedure TfrmMalen.GetPaint(Text: ShortString);
begin
     imgPapier.Canvas.Brush.Color := StringToColor(GetString('%', text, 7));
     imgPapier.Canvas.Pen.Color := imgPapier.Canvas.Brush.Color;
     imgPapier.Canvas.Pen.Width := GetInteger('%', Text, 6);
     imgPapier.Canvas.Brush.Style := bsClear;
     Case text[2] of
          'n': Begin
               imgPapier.Canvas.Brush.Color := clWhite;
               imgPapier.Canvas.Pen.Color := imgPapier.Canvas.Brush.Color;
               imgPapier.Canvas.Pen.Width := 1;
               imgPapier.Canvas.Brush.Style := bsSolid;
               frmMalen.imgPapier.Canvas.Rectangle(0, 0, imgPapier.Width, imgPapier.Height);
               end;
          'p': Begin
               frmMalen.imgPapier.Canvas.Pixels[GetInteger('%', Text, 2), GetInteger('%', Text, 3)] := imgPapier.Canvas.Brush.Color;
          end;
          'r': Begin
               frmMalen.imgPapier.Canvas.Rectangle(GetInteger('%', Text, 2), GetInteger('%', Text, 3), GetInteger('%', Text, 4), GetInteger('%', Text, 5));
          end;
          'e': Begin
               frmMalen.imgPapier.Canvas.Ellipse(GetInteger('%', Text, 2), GetInteger('%', Text, 3), GetInteger('%', Text, 4), GetInteger('%', Text, 5));
          end;
          'm': Begin
               frmMalen.imgPapier.Canvas.MoveTo(GetInteger('%', Text, 2), GetInteger('%', Text, 3));
               frmMalen.imgPapier.Canvas.LineTo(GetInteger('%', Text, 4), GetInteger('%', Text, 5));
          end;
     end; //Case
end;

procedure TfrmMalen.Schliessen1Click(Sender: TObject);
begin
     frmMalen.hide;
end;

procedure TfrmMalen.imgPapierMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
     Currentx := x; Currenty := y;
     If LMBGedruckt then begin
      frmMalen.Canvas.Pen.Width := speWidth.Value;
      If spbRectangle.Down then begin
         frmMalen.ImgPapier.Refresh;
         frmMalen.Canvas.Brush.Style := bsClear;
         frmMalen.Canvas.Rectangle(Startx + frmMalen.ImgPapier.Left, Starty + frmMalen.ImgPapier.Top, Currentx + frmMalen.ImgPapier.Left, Currenty + frmMalen.ImgPapier.Top);
      end;
      If spbEllipse.Down then begin
         frmMalen.ImgPapier.Refresh;
         frmMalen.Canvas.Brush.Style := bsClear;
         frmMalen.Canvas.Ellipse(Startx + frmMalen.ImgPapier.Left, Starty + frmMalen.ImgPapier.Top, Currentx + frmMalen.ImgPapier.Left, Currenty + frmMalen.ImgPapier.Top);
      end;
      if spbLine.Down then begin
         frmMalen.ImgPapier.Refresh;
         frmMalen.Canvas.Brush.Style := bsClear;
         frmMalen.Canvas.MoveTo(Startx + frmMalen.ImgPapier.Left, Starty + frmMalen.ImgPapier.Top);
         frmMalen.Canvas.LineTo(Currentx + frmMalen.ImgPapier.Left, Currenty + frmMalen.ImgPapier.Top);
      end;
     end;
end;

procedure TfrmMalen.imgPapierMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   Currentx := x; currenty := y;
   IF LMBGedruckt then begin
      If spbRectangle.Down then SendToPuffer('r');
      If spbEllipse.Down then SendToPuffer('e');
      if spbLine.Down then SendToPuffer('m');
   end;
   LMBGedruckt := false;
   MMBGedruckt := false;
   RMBGedruckt := false;
end;

procedure TfrmMalen.imgPapierMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
   Startx :=  X; Starty := Y;
   If Button = mbLeft then LMBGedruckt := true;
   If Button = mbMiddle then MMBGedruckt := true;
   If Button = mbRight then RMBGedruckt := true;
end;

procedure TfrmMalen.FormCreate(Sender: TObject);
begin
   frmMalen.imgPapier.Canvas.Create;
   LMBGedruckt := false;
   MMBGedruckt := false;
   RMBGedruckt := false;
end;

procedure TfrmMalen.FormClose(Sender: TObject; var Action: TCloseAction);
begin
     MPuffer.Free;
     Malen.Free;
end;

procedure TfrmMalen.ShapeColorMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
     frmMalen.cdbColor.Execute;
     frmMalen.ShapeColor.Brush.Color := frmMalen.cdbColor.Color;
     frmMalen.Canvas.Brush.Color := frmMalen.cdbColor.Color;
     frmMalen.Canvas.Pen.Color := frmMalen.cdbColor.Color;
end;

procedure TfrmMalen.tmrPufferTimer(Sender: TObject);
var Text: ShortString;
begin
   If MPuffer.Count > 0 then begin
     Malen := MPuffer.Items[0];
     Text := '%p%' + Malen.Werkzeug + '%' + IntToStr(Malen.x1) + '%' + IntToStr(Malen.y1) + '%' + IntToStr(Malen.x2) + '%' + IntToStr(Malen.y2) + '%' + IntToStr(Malen.Dicke) + '%';
     Text := Text + ColorToString(Malen.Farbe) + '%' + Malen.Absender + '%';
     frmMalen.Send(Text);
     MPuffer.Delete(0);
   end else begin
       MPuffer.Clear;
   end;
end;

procedure TfrmMalen.Neu1Click(Sender: TObject);
begin
     SendToPuffer('n');
end;

begin
     MPuffer := TList.Create;
     Malen := TMalen.Create;
end.

Hier ist noch eine Antwort auf den Twitter Tweet, in dem die Frage aufkam, was man vor 10 Jahren programmiert hat.
Vor genau 10 Jahren steckte ich mitten im Abitur und habe mit einem Freund zusammen ein Netzwerkmanagement-Tool entwickelt. Entwicklungsumgebung war Borland Delphi (Client) und Borland C++ Builder (Server). Damit konnten wir in dem kleinen Schulnetzwerk Programme auf den Clients ausführen, Informationen über den Status abrufen und die Clients neu Starten. Der Server hatte ein fest codiertes Bild des Computerraumes mit den Clients, dem Staus und den Funktionen. Der Code ist leider im Laufe der Zeit verschwunden.

Im Jahr 1997 habe ich mir die Mühe gemacht, nicht “nur” die Aufgaben zu lösen sondern auch die Lösungen schriftlich auszuarbeiten. Die Rede ist von meiner Teilnahme am 16. Bundeswettbewerb Informatik. Meine Ausarbeitung war leider so schlecht, dass ich noch nicht einmal die erste Runde geschafft habe. Für alle, die sich den Aufgaben auch einmal stellen möchten, sind hier die Aufgaben.

Das erste Programm oder der erste Algorithmus, an den ich mich erinnern kann war -wie könnte es anders sein- ein Programm zum Berechnen von Primzahlen. Es war 1993(!) auf einem C64 und die Berechnung hat echt lange gedauert. Der Nadel-Drucker hat mich Nacht um Nacht wach gehalten, um alle paar Minuten eine Zeile mit 5 oder 6 Primzahlen zu drucken…auf Endlospapier -Gott hab es seelig.
Ich werde wohl die nächsten Tage mal meine alten Disketten vom Speicher holen und mal schauen, was sich dort alles findet.

Schon einmal einen Programmierer sagen hören “Diese neue Technologie ist cool. Die sollten wir einsetzen”. Hört man auf den Programmierer und setzt die Technologie einfach ein? Wie ist das denn wenn der Kunde sagt “Diese neue Technologie ist cool. Die solltet ihr einsetzen”. Sollte man die Technologie jetzt einsetzen? Neue Technologien bieten auch neue Chancen für das Produkt und neue Motivation für Entwickler.

Der erste Schritt liegt auf der Hand. Mittels eines Proof Of Concept wird die neue Technologie getestet und verifiziert, ob die Technologie zur Architektur passt. Aber wie geht es weiter? Die folgenden fünf Fragen geben eine Entscheidungshilfe für die Entscheidung.

  • Erfüllt die Technologie die Anforderungen an die Architektur?
  • Will der Kunde diese Technologie haben?
  • Wollen die Entwickler diese Technologie einsetzen?
  • Wie groß ist der Einfluss der Technologie auf den bestehenden Code?
  • Wie leicht lässt sich diese Technologie bei einer Fehlauswahl wieder entfernen?

Zu guter letzt muss wieder der Architekt entscheiden, aber doch bitte bewusst und nach objektiven Kriterien und nicht nach Bauchgefühl.

Powered by WordPress Web Design by SRS Solutions © 2010 Think First Development Design by SRS Solutions