image image Home   About   Downloads   Support   Links   Contact  
image
Comparisons 
» ASP.net 
» Express Web Framework 
» WebSnap





Copyright
2002 - 2009
Atozed Computer
Software Ltd.

image
Buy Online   Download Support  FAQ Questions
Atozed Home  »  IntraWeb  »  Compare

IntraWeb and WebSnap - Guess

Is WebSnap RAD? WebSnap is a capable framework, but not quite RAD in the manner that most users think of RAD. When users think of RAD, typically visual development is what comes to mind. Here we will compare two implementations of the same application, one written in IntraWeb, the other in WebSnap.

Application

We have chosen a very simple application to compare the two tools. We chose a simple application for two reasons:

  1. So you can quickly see the differences in the tools without having to spend a lot of time understanding the application itself.
  2. To show you how drastic the differences are with a simple application. The differences in implementation grow significantly larger as the copmplexity of the application increases.

The application is a simple guess the number game that validates user input, counts guesses, and terminates when the user has guessed the magic number.

IntraWeb Implementation

The IntraWeb application was developed by the IntraWeb development team without using any add ons other than IntraWeb itself.

WebSnap Implementation

We wanted to make sure that our comparison was a fair one, so the WebSnap demo was developed by well known WebSnap expert Jimmy Tharpe. Jimmy is quite prominent and respected on the websnap newsgroup at newsgroups.borland.com as an expert on WebSnap, WebBroker and web development technologies.

The WebSnap implementation was developed using only WebSnap in an 'out of the box' manner. It has also been reviewed by other WebSnap users.

Implementation Notes

Both demos were developed using only components included in their respective products. No special components were added or created.

You Choose

We will let you choose. We will present both implementations to you, unlabeled. You choose which one is more like developing a normal Delphi application.

We will also tell you that Implementation A took about 5 minutes including debugging. Implementation B took well over an hour to produce and debug. Lets round it down to an hour. Thats productivity X 12!!!!

After you are done comparing the implementations, compare the feature differences.

 

Implementation A Implementation B

Files

  1. GuessDLL.dpr
  2. GuessDLL.res
    (Binary, not displayed below)
  3. Main.dfm
  4. Main.pas
  5. ServerController.dfm
  6. ServerController.pas

Files

  1. GuessWebSnap.dpr
  2. GuessWebSnap.res
    (Binary, not displayed below)
  3. Unit2.dfm
  4. Unit2.pas
  5. Unit2.html
  6. Unit3.html
  7. Unit4.html

GUESS.DPR

library GuessDLL;
uses
  IWInit,
  Main in 'Main.pas' {formMain: TIWFormModuleBase},
  ServerController in 'ServerController.pas'
   {IWServerController: TDataModule};

{{$$}$R *.res}
begin
  IWRun(TFormMain, TIWServerController, stISAPI);
end.

MAIN.DFM

[Image]

MAIN.PAS

unit Main;

interface uses
  IWAppForm, IWApplication,
  SysUtils, Classes,
  Controls, IWHTMLControls, IWControl, IWCompButton,
  IWCompLabel, IWCompEdit;

type
  TformMain = class(TIWAppForm)
    editGuess: TIWEdit;
    IWLabel1: TIWLabel;
    IWLabel2: TIWLabel;
    butnGuess: TIWButton;
    lablResponse: TIWLabel;
    lablGuessNo: TIWLabel;
    linkQuit: TIWLink;
    procedure IWFormModuleBaseCreate(Sender: TObject);
    procedure butnGuessClick(Sender: TObject);
    procedure linkQuitClick(Sender: TObject);
  protected
    FGuessCount: Integer;
    FMagicNo: Integer;
  public end;

implementation
{{$$}$R *.dfm}
procedure TformMain.IWFormModuleBaseCreate(Sender: TObject);
begin
  FMagicNo := Random(100) + 1;
  FGuessCount := 1;
end;

procedure TformMain.butnGuessClick(Sender: TObject);
var
  LGuess: Integer;
begin
  lablResponse.Caption := '';
  LGuess := StrToIntDef(Trim(editGuess.Text), MaxInt);
  if LGuess = MaxInt then begin
    WebApplication.ShowMessage(editGuess.Text
     + ' is not a valid number.');
  end else if (LGuess < 1) or (LGuess > 100) then begin
    WebApplication.ShowMessage(
     'Only numbers between 1 and 100 are valid.');
  end else if LGuess < FMagicNo then begin
    lablResponse.Caption := IntToStr(LGuess)
     + ' is too low.';
    Inc(FGuessCount);
  end else if LGuess > FMagicNo then begin
    lablResponse.Caption := IntToStr(LGuess)
     + ' is too high.';
    Inc(FGuessCount);
  end else if LGuess = FMagicNo then begin
    WebApplication.Terminate('Fantastic! You guessed it in '
     + IntToStr(FGuessCount) + ' guesses.');
  end;
  lablResponse.Visible := Length(lablResponse.Caption) > 0;
  lablGuessNo.Caption := 'Guess #' + IntToStr(FGuessCount);
  editGuess.Text := '';
end;

procedure TformMain.linkQuitClick(Sender: TObject);
begin
  WebApplication.Terminate('Thank you for playing!');
end;

initialization
  Randomize;
end.

SERVERCONTROLLER.DFM

[Image]

SERVERCONTROLLER.PAS

unit ServerController;

interface uses
  SysUtils, Classes, Forms, IWServerControllerBase;

type
  TIWServerController = class(TIWServerControllerBase)
  private public end;

implementation
{{$$}$R *.DFM}
end.

GUESSWEBSNAP.DPR

library GuessWebSnap;

uses
  WebBroker,
  ISAPIThreadPool,
  ISAPIApp,
  Unit2 in 'Unit2.pas' {Guess: TWebAppPageModule}
{*.html};

{{$$}$R *.RES}
exports
  GetExtentionVersion,
  HTTPExtensionProc,
  TerminateExtesnsion;

begin
  Application.Initialize;
  Application.Run;
end.

UNIT2.DFM

[Image]

UNIT2.PAS

unit Unit2;

interface uses
  Windows, Messages, SysUtils, Classes, HTTPApp,
  WebModu, HTTPProd, ReqMulti,
  WebDisp, WebAdapt, WebComp, WebSess, MidItems,
  WebForm, CompProd, PagItems, SiteProd;

type
  TGuess = class(TWebAppPageModule)
    PageProducer: TPageProducer;
    WebAppComponents: TWebAppComponents;
    ApplicationAdapter: TApplicationAdapter;
    PageDispatcher: TPageDispatcher;
    AdapterDispatcher: TAdapterDispatcher;
    SessionsService1: TSessionsService;
    GuessData: TAdapter;
    GuessAct: TAdapterAction;
    GuessCountField: TAdapterField;
    TextResponseField: TAdapterField;
    DoAlertField: TAdapterBooleanField;
    GuessField: TAdapterField;
    ExitAppAct: TAdapterAction;
    procedure SessionsService1StartSession(
     ASender: TObject; ASession: TAbstractWebSession);
    procedure GuessActExecute(Sender: TObject;
     Params: TStrings);
    procedure GuessCountFieldGetValue(Sender: TObject;
     var Value: Variant);
    procedure DoAlertFieldGetValue(Sender: TObject;
     var Value: Boolean);
    procedure TextResponseFieldGetValue(
     Sender: TObject; var Value: Variant);
    procedure GuessFieldGetValue(Sender: TObject;
     var Value: Variant);
    procedure ExitAppActExecute(Sender: TObject;
     Params: TStrings);
  private
{ Private declarations }
public
{ Public declarations }
end;

  function Guess: TGuess;

implementation
{{$$}$R *.dfm}
{*.html}
uses WebReq, WebCntxt, WebFact, Variants;

function Guess: TGuess;
begin
  Result := TGuess(WebContext.FindModuleClass(TGuess));
end;

procedure TGuess.GuessActExecute(Sender: TObject;
 Params: TStrings);
  var
    Guess: integer;
    GuessCount: integer;
    MagicNumber: integer;
begin
  MagicNumber := Session.Values['MagicNumber'];
  GuessCount  := Session.Values['GuessCount'];
  Inc(GuessCount);

  Guess := 
   StrToIntDef(Request.ContentFields.Values['UserGuess']
   , MaxInt);

  // Must set session value instead of
// adapter value since it's read-only :(
  Session.Values['DoAlert'] := False; 
  if Guess = MaxInt then begin
    // to show alert instead of message on page
    Session.Values['DoAlert'] := True; 
    Session.Values['TextResponse'] := 
     Request.ContentFields.Values['UserGuess'] +
     ' is not a valid number.'
  end else if (Guess < 1) or (Guess > 100) then begin
    Session.Values['DoAlert'] := True;
    Session.Values['TextResponse'] :=
     'Only numbers between 1 and 100 are valid.'
  end else if Guess < MagicNumber then
    Session.Values['TextResponse'] := 
     IntToStr(Guess) + ' is too low.'
  else if Guess > MagicNumber then
    Session.Values['TextResponse'] :=
     IntToStr(Guess) + ' is too high.'
  else if Guess = MagicNumber then begin
    Session.Terminate;
    DispatchPageName('CorrectGuessPage', Response, [])
    // Must manually dispatch page since there is no 
    // good way to set a
session-terminated page.
end;

  Session.Values['GuessCount'] := GuessCount;
end;

procedure TGuess.ExitAppActExecute(Sender: TObject;
 Params: TStrings);
begin
  Session.Terminate;
  DispatchPageName('ExitPage', Response, [])
end;

procedure TGuess.SessionsService1StartSession(
 ASender: TObject; ASession: TAbstractWebSession);
begin
// Initialize the session data
  Session.Values['GuessCount']  := 1;
  Session.Values['MagicNumber'] := Random(100) + 1;
end;

procedure TGuess.GuessCountFieldGetValue(Sender: TObject;
 var Value: Variant);
begin
// Values are read-only so we can't just set them.
  // Instead we have to write
additional event code
  // to get them.
  Value := Session.Values['GuessCount'];
end;

procedure TGuess.DoAlertFieldGetValue(Sender: TObject;
 var Value: Boolean);
begin
  Value := Session.Values['DoAlert'];
end;

procedure TGuess.TextResponseFieldGetValue(
 Sender: TObject; var Value: Variant);
begin
  Value := Session.Values['TextResponse'];
end;

procedure TGuess.GuessFieldGetValue(Sender: TObject;
 var Value: Variant);
begin
  Request.ContentFields.Values['UserGuess'];
end;

initialization if WebRequestHandler <> nil then begin
    WebRequestHandler.AddWebModuleFactory(
     TWebAppPageModuleFactory.Create(TGuess, 
     TWebPageInfo.Create([wpPublished], '.html', '',
     'Guess The Number'), caCache));
WebRequestHandler.AddWebModuleFactory( TWebPageModuleFactory.Create(TGuess, TWebPageInfo.Create([wpPublished], 'Unit3.html', 'CorrectGuessPage'), crOnDemand, caCache));
WebRequestHandler.AddWebModuleFactory( TWebPageModuleFactory.Create(TGuess, TWebPageInfo.Create([wpPublished], 'Unit4.html', 'ExitPage'), crOnDemand, caCache));
end; Randomize; end.

UNIT2.HTML

<html>
<head>
<%
vGuessData = Modules.Guess.GuessData
vGuessData_GuessCount = vGuessData.GuessCount
vGuessData_TextResponse = vGuessData.TextResponse
vGuessData_DoAlert = vGuessData.DoAlert
vGuessData_Guess = vGuessData.Guess
vGuessData_ExitApp = vGuessData.ExitApp
%>
</head>
<body>
<form name="GuessForm" method="post">
Please guess the number from 1 to 100:&nbsp;
<p>Guess:
<input type="text" name="UserGuess" value="<%= vGuessData_Guess.EditText %>" size="20" >
<input type="submit" value="Guess" onclick="GuessForm.__act.value= '<%=vGuessData_Guess.LinkToPage( "Guess", Page.Name).AsFieldValue%>'">
</p>
<p>Guess #: <%= vGuessData_GuessCount.DisplayText %> <input type="hidden" name="__act"></p><%
if (vGuessData_DoAlert.value){ %>
<script language="JavaScript">
alert("<%=vGuessData_TextResponse.DisplayText%>");
</script><%
}else{ %>
<%=vGuessData_TextResponse.DisplayText%><%
}%>
<p align="right">
<a href="" onclick="GuessForm.__act.value= '<%=vGuessData_ExitApp.LinkToPage( Page.Name, Page.Name).AsFieldValue%>'; GuessForm.submit();return false;"> Exit</a>
</p>
</form>
</body>
</html>

UNIT3.HTML

<html>
<head>
<title>
<%= Page.Title %>
</title>
</head>
<body>
You guessed correct!
</body>
</html>

UNIT4.HTML

<html>
<head>
<title>
<%= Page.Title %>
</title>
</head>
<body>
Thanks for playing.
</body>
</html>

 




CodeGear - Where Developers Matter