tag:blogger.com,1999:blog-33394598757550881132024-03-05T00:32:50.887-07:00Rob’s Technology CornerMy blog typically about Delphi Programming.Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.comBlogger87125tag:blogger.com,1999:blog-3339459875755088113.post-36005071704331643782019-04-02T19:19:00.001-06:002019-04-02T19:19:48.582-06:00A new problem, a new stack <div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVouiH7hJ5Ex88r8vR-KlUgWd63wuVgPUqQUMDVCFXv3P89iuOesxDJzmA11MHYRVjtvolbEOMt0sfGoD7wFeG75cMqUBWnwDpKEglii-nTy_zqEFAI-B0PhMzmJThyEskeRam-R3r64eQ/s1600/Delphi2010.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="130" data-original-width="130" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVouiH7hJ5Ex88r8vR-KlUgWd63wuVgPUqQUMDVCFXv3P89iuOesxDJzmA11MHYRVjtvolbEOMt0sfGoD7wFeG75cMqUBWnwDpKEglii-nTy_zqEFAI-B0PhMzmJThyEskeRam-R3r64eQ/s200/Delphi2010.jpg" width="200" /></a></div>
<h2>
Time to Rewrite</h2>
In the past year, my employer decided to rewrite our Internal Application. It's not something we took lightly, the current Delphi Application is over 5 Million lines of code. So as we rewrite portions of that existing application we will need to maintain our existing Delphi application so I will continue to use Delphi for at least 4-5 more years. Our system was released in 1999 as a Y2K project. Most of the original code was had the business rules right in button events, and a majority of that still exists. With my employer, it is unheard of to have an application survive 20 years, and it will most likely be 25 years old when we turn it off. It says a lot about our staff and Delphi. <div>
<br /></div>
<h3>
User Devices are always changing</h3>
<div>
However, I have always believed we should use the right tools for the job at hand. Our infrastructure is greatly changing, we now have a few telecommuters, with a push to support more. This is not friendly to our existing VCL Client Server Application. We have a mixed environment of Desktop PC, Macs, Tablets and have to be prepared to support the ever-changing device form factors. Our user's desktops are locked down with no administrative rights. Implementing Continuous Deployment with a desktop application has been increasing more difficult to manage.</div>
<div>
<br /></div>
<div>
We decided it was best to create a browser-based application. That is really not something Delphi is a market leader in so a change was in order. Having now spent several months of development using our new stack I am very pleased with this decision. </div>
<h2>
New Development Stack</h2>
<h3>
Front end</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY6Do_FY3S_HgZqRXOjKFuAxkNBMsB9aWrYRPxjkyq_8pH_ppTcznw17QnlORqacikOenH_8HaAo-YD96DRt2kNhpUt9Yzj-QxtBvZVNNDe4tFYlb0ErWQkkfS-pkIKIF0fJ5U8ysG4_uO/s1600/Angular_full_color_logo.svg.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="250" data-original-width="250" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY6Do_FY3S_HgZqRXOjKFuAxkNBMsB9aWrYRPxjkyq_8pH_ppTcznw17QnlORqacikOenH_8HaAo-YD96DRt2kNhpUt9Yzj-QxtBvZVNNDe4tFYlb0ErWQkkfS-pkIKIF0fJ5U8ysG4_uO/s200/Angular_full_color_logo.svg.png" width="200" /></a></div>
<div>
We are using <a href="https://angular.io/">Angular</a> 7+ with strict compiler settings on the <a href="https://www.typescriptlang.org/">TypeScript</a> compiler. This Angular CLI provided a huge selling point, it provided much of the front end stack without having to build it up. Angular provided a component model and TypeScript syntax that reminds me of Delphi helped with the learning curve on the transition. </div>
<div>
<br /></div>
<div>
We looked at the ever changing component lanscape with Angular. We spent a few weeks and decided to write own library that provides a facade around the <a href="https://www.primefaces.org/primeng/#/">PrimeNg</a> Controls. This allows a majority of our front end to not care about the underlying library, if control is deprecated or problematic we can swap it out without impacting the rest of the application.</div>
<div>
<br /></div>
<div>
The browser world is always changing, It's a major moving target, things like <a href="https://webassembly.org/">web assembly</a> may really change the landscape in this space. As such it's critical to avoid tightly coupling the various parts of our application. We are using Visual Studio Code as the editor of all our front end work and I highly recommend it.</div>
<div>
<br /></div>
<h3>
<b>Back end</b></h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBD9lRGgzU4pBuBaiETm1m2t3h1dZIK2zhzszo5N4ddw1AQw_E4BwmLrX-gyFnFaH378BOqqNI7FKsRqK3cv_FvX5uZ9Dr6OqzIXmUqXfd8KW_cnNbDz6xNkAobGiU-SKyw77libKOAjRC/s1600/Csharp_Logo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBD9lRGgzU4pBuBaiETm1m2t3h1dZIK2zhzszo5N4ddw1AQw_E4BwmLrX-gyFnFaH378BOqqNI7FKsRqK3cv_FvX5uZ9Dr6OqzIXmUqXfd8KW_cnNbDz6xNkAobGiU-SKyw77libKOAjRC/s200/Csharp_Logo.png" width="200" /></a></div>
<div>
The backend is a series of <a href="https://en.wikipedia.org/wiki/Representational_state_transfer">REST</a> endpoints written using<a href="https://dotnet.microsoft.com/"> C# and ASP.NET Web API</a>. We have no user-facing ASP.NET pages. We now also provide a real-time client to client communication channel implement <a href="https://dotnet.microsoft.com/apps/aspnet/real-time">SignalR</a>, which has increased our ability for our users to collaborate in our application. </div>
<div>
<br /></div>
<div>
Our data layers are abstracted and loosely coupled to our business rules which has greatly enhanced our ability to unit test, and we chose <a href="https://xunit.net/">XUnit</a> to help us with that. Which has in turn increase our quality. </div>
<div>
<br /></div>
<div>
We are using <a href="https://docs.microsoft.com/en-us/ef/">Entity Framework </a>to managed our database access, which came with a bit of a learning curve as someone who has used SQL for some many years. But now after using <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/">LINQ</a>, I have found it really easy to use and so far as produced performant access to our data. </div>
<div>
<br /></div>
<div>
We are using Visual Studio 2017 Professional for our back end code, and we will eventually be upgrading to Visual Studio 2019 which was released today.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com1tag:blogger.com,1999:blog-3339459875755088113.post-8909421731104263842017-03-28T09:04:00.000-06:002017-03-28T09:04:44.469-06:00The Value of Code ReviewsI have recently seen code that that looked like this.<br />
<pre class="brush:delphi">
try
... Lines of Code here ...
except
end;
</pre>
or
<br />
<pre class="brush:delphi">
procedure TCustomClass.MethodDoThis()
begin
... 20 Lines of code ...
end;
procedure TCustomClass.MethodDoThis2()
begin
... Same 20 Lines of code with slight modification ...
end;
</pre>
Both produced code that may have passed end user testing. But both cause long-term problems. <br />
<ul>
<li>The first example was just hiding all exceptions, a bad practice. After the code review, it was determined that the try | except block was not even needed. </li>
<li>The second example was refactored to reduce the need for duplicate code. The duplicate code causes problems when someone has to make changes that would apply to both methods but does not notice the 2nd method and therefore neglects to change it.</ul>
</ul>
<b>My point is simple, code reviews have value.</b>
<br />
<br />
Sidenote: Looking forward to reviewing <a href="http://blog.marcocantu.com/blog/2017-march-delphi-102-released-today.html">Tokyo release of Delphi</a> soon. With <a href="http://edn.embarcadero.com/article/44747">500+ Bug Fixes</a> with many in areas that impact our system is definitely worth investigating. Security and Quality go hand in hand, and I appreciate work to improve security. Typically, security issues are related to bugs in code that are exploited by hackers.
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com3tag:blogger.com,1999:blog-3339459875755088113.post-9336481421316005592016-07-28T12:58:00.000-06:002016-07-28T12:58:49.892-06:00Ideara / Embaracdero is flushing away user trust in their ability to do secure computing.In today's computing society you have to think of security first in the design of everything you do.<br />
<br />
It's costly to retrofit security. In my job I have think about security every day.
The costs of sensitive data escaping is too big to ignore. Trust is a huge word in security. I have to trust the vendors we use, that they will act quickly to resolve security issues. So we are not left vulnerable. A good vendor realizes there will be security problems and has a way to publicly communicate that has does so in an open and transparent method.<br />
<br />
Over 10 months ago I sent Embarcadero management several problems with Embarcadero's websites. I finally saw a bit of action after the main website
was hacked quickly after it went live. I even talked with Atanas Popov the General Manager of Embarcadero. But after that they went dark and have not communicated with me regarding security since. It's clear they have no plans to create a place on where we can go learn about security issues and the fixes that may have occurred in the product. <br />
<br />
I also called for them to hire a CSIO and empower them, which clearly has not happened. Even if they did not have a CSIO, they need security to be monitored and prioritized.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYIH7wRRrw3AZt-IfF3ol5rMj735lIx9BGsg2SjzzUePWjdH2_xjZuVftREVRdPs2025-YHhClzgDRXveFC3kmjsDxDGoKTTk_Zc4wg0f7JvhzbX6krrGCLPfYJOSPBloD-XQrmbPQIqAg/s1600/FlushedBySecurityMisManagement.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYIH7wRRrw3AZt-IfF3ol5rMj735lIx9BGsg2SjzzUePWjdH2_xjZuVftREVRdPs2025-YHhClzgDRXveFC3kmjsDxDGoKTTk_Zc4wg0f7JvhzbX6krrGCLPfYJOSPBloD-XQrmbPQIqAg/s320/FlushedBySecurityMisManagement.png" width="320" /></a></div>
Today I received a plaintext password in email for an <a href="http://community.idera.com/">Idera Community website</a>. Have they not heard about hashing passwords? A hashed password can not be sent in clear text. In email they claimed it was stored securely, and they did it this way to prevent spam. But what they did was give passwords out insecurely which could enable more spam instead of reduce it. They defended this action and clearly thought the practice was ok. They offered to delete my account. I did not request the account so I took them up on the offer. Regardless maybe they should <a href="https://youtu.be/Qw3rx3IEqp0?t=6m30s">watch the password portion of my session</a> I did for them at CodeRageX. <br />
<br />
<a href="https://www.idera.com/">Idera </a>and <a href="https://www.embarcadero.com/">Embarcadero</a> are clueless when it comes to website security. Maybe just websites in general since Embarcadero's website is now serving content to me in Portuguese even when I select English.<br />
<br />
<b>I have NO TRUST in SECURITY from Idera or Embarcadero at this point. </b><br />
<br />
Moving too slowly on a security vulnerability is like using and flushing a clogged toilet, bad things will happen. Being vulgar and swearing is not in my character, however, it was very very hard not to be that way in this post. I have invested decades in a company and product that I can see clogged in their own toilet water.Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com6tag:blogger.com,1999:blog-3339459875755088113.post-16526738387470620212016-07-08T11:55:00.000-06:002016-07-08T11:59:14.784-06:00Code in Application or the database?My employer has a fairly large Delphi application with ~5 Million lines of pascal code.<br />
<br />
They have a large database and use Oracle 12c to manage it.<br />
<br />
I have seen many methodologies on how to manage your database access code.<br />
On the edges I see two extremes are:<br />
<br />
<ul>
<li>Do everything in Stored Procedures </li>
<li>Do everything in Code outside the database, (Typical ORM)</li>
</ul>
<div>
I believe you need to use the best tool for the job. So sometimes we are doing massive amounts of data processing that never leaves the database. For that I use Packages/Stored Procedures in Oracle. </div>
<div>
<br /></div>
<div>
Years ago we had a process that was 100% in code, and it took 20+ hours in code to execute, due to the round trips to the database. When we looked at optimization, it was clear that network time was a huge part of the equation. This Delphi process was converted to Oracle PL/SQL and was further optimized and our time was was reduced to <30 minutes</div>
<div>
<br /></div>
<div>
A simple example using the best tool for the job. I have been a advocate of unit testing in Delphi. Several months ago we had do some major PL/SQL work that resulted in about 50k lines of PL/SQL code. Way too many lines of code to write and trust without sometime of unit testing framework. We had been testing PL/SQL code from Delphi using <a href="https://github.com/VSoftTechnologies/DUnitX">DUnitX</a>, but it was one too many steps away from the code under test. I started working with <a href="https://utplsql.github.io/">utPLSQL</a> a user testing framework for PL/SQL. </div>
<div>
<br /></div>
<div>
In the past few weeks: I finished the move of utPLSQL from SourceForge to <a href="https://github.com/utPLSQL/utPLSQL">GitHub</a>, and have released <a href="https://utplsql.github.io/moving/2016/07/07/version-2-3-1-released.html">version 2.3.1 of utPLSQL</a>.</div>
<div>
<br /></div>
<div>
Still love and use <a href="https://github.com/VSoftTechnologies/DUnitX">DUnitX</a> but I use it from my Delphi Code not my PL/SQL code.</div>
<div>
<br /></div>
<div>
Regardless of the technology you find yourself using for development you need to unit test.</div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com1tag:blogger.com,1999:blog-3339459875755088113.post-62658780494130450712016-04-21T11:16:00.001-06:002016-04-21T11:16:42.796-06:00Rad Studio Berlin 10.1 - First Look via TwitterToday I installed <a href="https://www.embarcadero.com/products/rad-studio">Rad Studio 10.1 Berlin</a>. This was my first chance to look at it. <br />
Here are some the tweets are shared earlier today.<br />
<div>
<br /></div>
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
Just installed Rad Studio 10.1 Berlin. Loved the new install experience.</div>
— Robert Love (@DelphiDev) <a href="https://twitter.com/DelphiDev/status/723155449147625473">April 21, 2016</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>
<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
Rad Studio 10.1 Berlin has a new welcome page. It's very clean, easy to use. Thank you RSP-11183 can now be closed <a href="https://t.co/3gzSLXKw3F">pic.twitter.com/3gzSLXKw3F</a></div>
— Robert Love (@DelphiDev) <a href="https://twitter.com/DelphiDev/status/723156731673505797">April 21, 2016</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>
<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
Rad Studio 10.1 Berlin - Cool New Feature. Press Ctrl-W to expand syntax selection. <a href="https://t.co/FsgkCWnO3c">pic.twitter.com/FsgkCWnO3c</a></div>
— Robert Love (@DelphiDev) <a href="https://twitter.com/DelphiDev/status/723172913843572740">April 21, 2016</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>
<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
Rad Studio 10.1 Berlin, supports a great list of Z-Wave and Bluetooth IOT devices. <a href="https://t.co/KNULTKfzLB">pic.twitter.com/KNULTKfzLB</a></div>
— Robert Love (@DelphiDev) <a href="https://twitter.com/DelphiDev/status/723181019432525824">April 21, 2016</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com0tag:blogger.com,1999:blog-3339459875755088113.post-32513836048591882272016-04-19T10:05:00.002-06:002016-04-19T10:05:24.387-06:00SQL Injection - Stored Procedures Security needs to be multiple levels deep. At one point in time several years ago there was a trend to have all websites code use stored procedures. I heard developers say it prevented SQL Injection.<br />
<br />
If the database you use allows you to build SQL statements with a string dynamically at run time in a stored procedure then you can have SQL injection in a Stored Procedure. <br />
<br />
Each Database slightly different syntax and guidelines:<br />
<br />
<ul>
<li><a href="https://www.integrigy.com/files/Integrigy_Oracle_SQL_Injection_Attacks.pdf">Oracle </a> (See Page 12)</li>
<li><a href="http://stackoverflow.com/questions/627918/am-i-safe-against-sql-injection">PostgesSQL</a> </li>
<li><a href="https://blogs.msdn.microsoft.com/brian_swan/2011/02/16/do-stored-procedures-protect-against-sql-injection/">SQL Server</a></li>
</ul>
<br />
<ul></ul>
<br />
<div>
In short: If your doing dynamic SQL inside your Stored Procedures you will have validate the input otherwise you can be impacted.</div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com0tag:blogger.com,1999:blog-3339459875755088113.post-37807361716353861782016-04-18T15:17:00.000-06:002016-04-18T15:18:02.449-06:00SQL InjectionI just wrote a blog posts on <a href="http://robstechcorner.blogspot.com/2016/04/security-assumptions.html">security assumptions</a>. I realized there was a huge missing assumption. (This has since been updated.)<br />
<br />
<ul>
<li> Assume that all input can be malicious </li>
</ul>
<br />
Today I want to show the most common mistake, and exploit that I have ever seen. It impacts all languages and all SQL Based databases. It's called <a href="https://en.wikipedia.org/wiki/SQL_injection">SQL Injection</a>. I have heard developers make the incorrect assumption that this only impacts web based applications. I have seen this problem in all types of applications that touch a database.<br />
<br />
Today's example is VCL Desktop application uses FireDAC to access a SQLite database.<br />
<br />
The example code used here can be found in the <a href="https://github.com/rlove/security-demo">security-demo GitHub repository</a>.<br />
<br />
SQL Injection occurs when you don't use Parameters, which allows input to modify your SQL statement.<br />
<br />
Here is the unsafe way to do it:
<br />
<pre class="brush:delphi">
FDQuery1.SQL.Add('select * from tbl1 where name like ''' + edtSearchTerm.Text +'%''');
FDQuery1.Open;
</pre>
<br />
With this example if I entered the following into edtSearchTerm.text
<br />
<pre>a ' union select name, sql from sqlite_master --
</pre>
<br />
I will get a list of tables in the database, with that it's simple to see that there another table called salary in the database. Where I can then enter the following to get all the salary information.
<br />
<pre>a ' union select name, value from salary --
</pre>
<br />
Here is the safe way to do it:
<br />
<pre class="brush:delphi"> FDQuery1.SQL.Add('select * from tbl1 where name like :name');
FDQuery1.ParamByName('name').asString := edtSearchTerm.Text + '%';
FDQuery1.Open;
</pre>
<br />
Now I can enter both strings that attempt SQL Injection and they will fail. This is because they end up inside the parameter and thereby can't modify the sql.
Simple to avoid, but still a common mistake that that is made when it comes to security. Testing for SQL Injection is pretty simple you enter try terminating the input with single and double quote. If you get an unexpected error odds are you have a possibility of SQL injection.<br />
<br />
We tend to focus on user input, but API's like SOAP or REST end points are also common targets for SQL Injection attacks. That is why I have been very careful to say <b>all input</b>, and not all just user input.
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com7tag:blogger.com,1999:blog-3339459875755088113.post-23492946518894504862016-04-16T23:00:00.000-06:002016-04-18T14:38:49.232-06:00Security assumptions <div class="MsoNormal">
When it comes to application security there is lots of
discussion on the Internet about web applications and network security. I however found far less information when it
comes to desktop applications and other applications that typically reside
behind a firewall.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
For example the initial version of App Tethering communication
was clear text. It has a password but it was sent in the
clear. The reasoning I was given that
the original was sent in clear text was that it was intended to be used behind
the firewall. This design flaw has
since been resolved. <br />
By default your data in the communication is still clear text, although your
passwords now use a HMAC method for authentication with each other. You
now have optional hooks where you can encrypt the data. Not
as nice as communicating over TLS, but is far more secure that the original
version.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I tend to take a different approach; I make the following
assumptions when it comes to security when I code something.</div>
<div class="MsoNormal">
<o:p></o:p></div>
<div class="MsoNormal">
</div>
<ul>
<li>Assume there is no
firewall and hackers can hit any server you publish.</li>
<li>Assume a server,
network switch or router on your network will be compromised and will be
collecting your data.</li>
<li>Assume the machine your code is on will be compromised and/or stolen.</li>
<li></li>
<li>Assume that all input can be malicious </li>
</ul>
<br />
<div class="MsoNormal">
<o:p></o:p></div>
<div class="MsoNormal">
Every day computers around the world are infected with
virus, malware, etc... <o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
These are sometimes these might have been caught by a
scanner and sometimes they can be slip past the scanner. So although a virus scanner is a good idea, it's not
perfect. Given that you have to assume that someone on your network
is infected, and a hacker now has access to a machine behind the firewall. </div>
<div class="MsoNormal">
<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If an application takes these assumptions into account
during its design, it will help prevent a data breach from occurring. <o:p></o:p></div>
<br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Data Breaches are costly just ask Target and Home
Depot. So spending some time upfront can
go a long way in reducing potential unexpected downstream costs.<o:p></o:p></div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com2tag:blogger.com,1999:blog-3339459875755088113.post-46297778799936354102016-04-06T12:01:00.000-06:002016-04-07T14:13:00.746-06:00New Rad Studio Coming - Security?<a href="https://attendee.gotowebinar.com/rt/8114586402052971010">On April 21st & 22nd there will be a Webinar that goes over the Highlights of RAD Studio</a>.<br />
<br />
Embarcadero presenters will discuss among other things the following topics:<br />
<ul>
<li> A new installation tool with GetIt technology and the choice of what you want to install </li>
<li> Extended support for Bluetooth LE on Windows 10 and a framework for IoT components </li>
<li> FireUI App Preview - Preview your forms on any target device (desktop or mobile)</li>
</ul>
<div>
It looks interesting, I have had many complaints with installer over the years for taking up too much disk space. I am also working on IoT devices (usually building them) every week now. So I am excited to any improvements in this area. </div>
<div>
<br /></div>
<div>
I also wonder how much of it will have improvements in the security areas that I have concerns with. Granted most of my concerns deal with the websites more than the product. I suspect I won't get the information I want in this webinar, but will only come through a review of the product. </div>
<div>
<br /></div>
<div>
I started contacting Embarcadero regarding several specific security issues on Aug 30, 2015 right before the Idera purchase. <a href="http://blog.marcocantu.com/blog/2015-december-features-10seattle-u1.html">Some of these were addressed: for example the community toolbar in Rad Studio no longer uses an unencrypted session when you log in. AppAnalytics uses HTTPS instead of HTTP.</a></div>
<br />
<div>
But nothing appeared to change on the websites then on <a href="https://plus.google.com/u/0/111269448785316370851/posts/RAdhQKVZoLM?cfem=1">March 12th Embacardero website was hacked</a>, After a couple of "I told you so" emails, problems were escalated. I produced a multi page security report detailing issues with every Embarcadero website. This finally generated some action. I had a very good call with Atanas Popov the General Manager of Embarcdero's Developer Tools we discussed how they can improve security on both the websites and products. I now know they are listening, I am now watching to see if the listening turns to action. </div>
<div>
<br /></div>
<div>
I love Delphi it's a great tool I want to see it succeed and has had a very positive impact on my career. Given that it's been really difficult to be positive for the past several months, so I have chosen instead to be quiet, but I believe it's time to be publicly vocal. In my job, I have to deal with security concerns all the time. My employer is constantly under attack. So harding systems and software is always a concern. So I am required to demand that from my from the vendors we use. If a vendor fails to take security seriously it has a huge negative impact my ability to use that vendor.</div>
<div>
<br /></div>
<div>
So here is to hoping we get some greater transparency and action on security issues. </div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com6tag:blogger.com,1999:blog-3339459875755088113.post-91986535295136977552016-04-03T18:30:00.000-06:002016-04-04T20:39:17.842-06:00Raspberry Pi 3 - Arrived and setup.After a bit of waiting my new <a href="https://www.raspberrypi.org/products/raspberry-pi-3-model-b/">Raspberry Pi 3 Model B</a> just arrived. <br />
<br />
I wanted to share a few of my steps I used in getting started and paired up with my Mac for easy development.<br />
<br />
Having played with both <a href="https://www.raspberrypi.org/downloads/raspbian/">Raspbian</a> and <a href="http://ms-iot.github.io/content/en-US/Downloads.htm">Microsoft IOT Core</a> with my <a href="https://www.raspberrypi.org/products/raspberry-pi-2-model-b/">Pi 2</a>. I currently<br />
prefer to use Raspbian, so this article will focus on that.<br />
<br />
1. <a href="https://www.raspberrypi.org/downloads/">Download & Install the Raspbian</a> on an SD Card.<br />
If you're not familiar with <b>dd</b> then you should consider using the <b>NOOBS</b> install method as it's painless.<br />
<br />
Raspbian is based on Debian Jessie or Jessie Lite (Depending on the choice you made) <br />
I used the one based on Jessie.<br />
<br />
2. Insert SD Card, Hook up Monitor, Mouse, Keyboard, and a network cable.<br />
<br />
3. By default the Raspbian installation ships with <b>pi</b> as the default user and <b>raspberry</b> as the default password. Unless you plan on keeping your Pi off of any network you need change this. It's just a matter of time until a worm will be developed looking to infect a Pi with a default password. So <a href="https://www.raspberrypi.org/documentation/linux/usage/users.md">change the default password</a> and if desired create and use a different user all together.<br />
<br />
4. As with all new OS installations you should perform updates right after installation.<br />
This is very good security practice. It's also the good to do on regular basis. <br />
<br />
To update Raspbian you use <b>apt-get</b><br />
The following two commands will get you updated.<br />
<br />
sudo apt-get update<br />
sudo apt-get dist-upgrade<br />
<br />
The first updates the list of packages.<br />
The second performs all of the upgrades and manages the dependencies that they require.<br />
<br />
You will want to do this on a regular basis to keep your machine updated.<br />
If you want you can <a href="https://www.debian-administration.org/article/162/A_short_introduction_to_cron-apt">setup cron to automatically do this</a>. After reading the article check out the comments for a good bash script, that will email you when updates are available.<br />
<br />
5. Change the hostname if you want. Since I have multiple pi's I rename each image to be unique.<br />
If you have the graphical interface you can select the following menu to rename the hostname.<br />
<br />
<ul>
<li>Menu (With the raspberry image on it)</li>
<li>Preferences</li>
<li>Raspberry Pi Configuration</li>
</ul>
<br />
If you don't have the gui you can <a href="http://raspberrypi.stackexchange.com/questions/3926/how-to-change-the-raspberry-pis-hostname-in-raspbmc">edit two files to change the hostname</a>.<br />
<br />
6. If you have Pi 3 or an earlier Pi with a USB Wifi Adapter you may want to <a href="https://www.raspberrypi.org/documentation/configuration/wireless/README.md">setup wireless</a>. <br />
<br />
7. Now I set up <a href="https://osxfuse.github.io/">Fuse for OSX</a> on my Mac so I can make my PI a mount point on mac. <a href="https://github.com/pubnub/workshop-raspberrypi/blob/master/SSHFS%2BMacFUSE.md">This article I found covers how to set this up</a>. This allows me to use editors on my Mac to edit files on my machine. I then use SSH to execute that code on the machine. I then can disconnect the keyboard, monitor, and mouse from the Pi as it's no longer required as I can use my main machine to easily control it.<br />
<br />
8. If you need <a href="https://www.raspberrypi.org/documentation/remote-access/vnc/">access to the graphical interface from your mac you can do that as well using VNC</a>, due the nature of what I want to do next I am not installing this at this time. <br />
<br />
9. Beware although this setup works. You are storing your code directly on the Pi. So when coding you do run this risk of losing your code if something bad happens. So since git is preinstalled on Raspbian, I tend to initialize a repository in my code directory, setup remote origin and push the changes to a remote repository. That way you don't lose your work that is on the pi. I love <a href="https://bitbucket.org/">BitBucket</a> for this as you can as many free private repositories as you want.<br />
<br />
<br />
<div>
<br /></div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com0tag:blogger.com,1999:blog-3339459875755088113.post-20257012835253526272015-10-14T11:09:00.000-06:002015-10-14T17:11:46.187-06:00CodeRageX - Security Session FilesFor those that were able to attend my <a href="http://www.embarcadero.com/coderage">CodeRage X</a> session. I had a few files I wanted to share. <br />
<br />
I intend to update them, so they may be better than the one shown in the presentation. However, they are in GIT so you can see the history if you want. When recordings are posted I will link to them here.<br />
<br />
Windows command script that allows you to generated self signed keys using OpenSSL. <br />
I intend to add a few other scripts and resolve some of the hard coding in the config files.<br />
<br />
<a href="https://github.com/rlove/OpenSSL-WinCmd-Snippets">https://github.com/rlove/OpenSSL-WinCmd-Snippets</a><br />
<br />
<br />
I also created a single project that demonstrates how to setup SSL/TLS with Indy and OpenSSL.<br />
That is also stored in a separate GIT Repository. I wanted to flush out the examples some more.<br />
<br />
The repository contains C++ and Object Pascal examples, even though the video was just in Object Pascal.<br />
<br />
<a href="https://github.com/rlove/Indy-SSL-Examples">https://github.com/rlove/Indy-SSL-Examples</a><br />
<br />
Although it may take me a couple of weeks to do updates, due to a vacation that will keep me offline. I will update both the repository and this post when that occurs.<br />
<br />
<br />
<br />Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com1tag:blogger.com,1999:blog-3339459875755088113.post-50986926569489349092015-06-20T14:03:00.000-06:002015-06-20T14:03:20.916-06:00XE8 Update 1 - Update Subscription<a href="http://delphi-insider.blogspot.com/2015/06/update-1-for-rad-studio-xe8-delphi-xe8.html">Update XE8 Update 1 was released</a> and there is two different versions of the update one for Update Subscription and one without.<br />
<br />
For several years now the company where I work as been on an Software & Maintenance for Rad Studio. The key benefits that I really like are:<br />
<br />
<ul>
<li>Support Incidents for when we run into a bug that we can not find a work around. They work with us to find a solution the problem at hand. Sometimes it's been a quick and easy problem for the support team and some time more difficult, ultimately we end up with something that works. One time we ended up with special version of the compiler to solve our problems so we could stay working. To be honest we don't have to contact support very often at all but it is nice to know it is there.</li>
<li>New version just arrive without having to deal with a purchasing nightmare, the budget stays relatively fixed so it's easy to plan the budget around the cost.</li>
<li>My entire team can participate in beta tests.</li>
</ul>
<div>
The Support and Maintenance program was recently was renamed to <a href="https://www.embarcadero.com/products/rad-studio/update-subscription">Update Subscription,</a> and some of the <a href="https://www.embarcadero.com/products/rad-studio/update-subscription">terms have changed</a>. Ultimately I believe these changes are good thing, but has some hurdles to get over, that some customers may not like. Specifically that customer need to be on Update Subscription to the full set of bug fixes. But some of the new terms allow for the following:</div>
<div>
<ul>
<li>Ongoing maintenance for up to 2 yrs for major version and up to 3 concurrent major versions. This really means that our XE6 and XE8 should be getting some of the bug fixes from XE8 coming to it. This is really helpful as we can't keep our entire code base current.</li>
<li>Webinars and web content that is just for Update Subscription customers. </li>
</ul>
<div>
We chose not to upgrade to XE8 as we have projects going on right now. These projects can't afford a delay that would come with an major upgrade the development tools. But under Update Subscription have value coming for XE6 and XE7 which we do use. I look forward to those releases but do wish we had an idea when they may be coming. </div>
</div>
<div>
<br /></div>
<div>
So in short I like the <a href="https://www.embarcadero.com/products/rad-studio/update-subscription">Update Subscription</a>. </div>
<div>
<br /></div>
<div>
<br /></div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com5tag:blogger.com,1999:blog-3339459875755088113.post-69736698634568254262015-02-19T14:38:00.001-07:002015-02-23T08:51:01.517-07:00PPL - TTask Exception ManagementRecently I wrote a blog post titled: "<a href="http://robstechcorner.blogspot.com/2015/02/tpl-ttask-example-in-how-not-to-use.html">PPL - TTask an example in how not to use.</a>"
The goal of that post was to help introduce some of the new thought processes that are required around multi-threaded programming.<br />
<br />
To keep GUI code responsive, threads can be used to keep time consuming code out of the Main thread where the GUI code runs. For example a good usage for this is database access, and calling web services. But, what happens when the database access or web service call fails? Using the same methodology as the prior blog post of doing it wrong first, this blog post now exists.<br />
<br />
I have modified the code from the <a href="http://robstechcorner.blogspot.com/2015/02/tpl-ttask-example-in-how-not-to-use.html">prior blog post</a>, where we dropped a listbox and button on a form. The new code now raises an exception during the execution.<br />
<pre class="brush:delphi">
procedure TForm5.Button1Click(Sender: TObject);
begin
Button1.Enabled := False;
SlowProc;
end;
procedure TForm5.FormDestroy(Sender: TObject);
begin
Task.Cancel;
end;
procedure TForm5.SlowProc;
begin
Task := TTask.Create( procedure
var
I : Integer;
begin
for I := 0 to 9 do
begin
if TTask.CurrentTask.Status = TTaskStatus.Canceled then
exit;
Sleep(1000);
if I = 2 then
raise EProgrammerNotFound.Create('Something bad just happened');
end;
if TTask.CurrentTask.Status <> TTaskStatus.Canceled then
begin
TThread.Queue(TThread.CurrentThread,
procedure
begin
if Assigned(ListBox1) then
begin
Listbox1.Items.Add('10 Seconds');
Button1.Enabled := True;
end;
end);
end;
end);
Task.Start;
end;
</pre>
When we run this code and press the button on the form the button is disabled and then nothing happens. The user gets no notification of the error. That is because the TTask has no way to notify the GUI of the exception. That is up to the developer. Never fail I know how exceptions work just wrap the code with a TRY EXCEPT block and raise it in the main thread.
<br />
<pre class="brush:delphi">
procedure TForm5.SlowProc;
begin
Task := TTask.Create( procedure
var
I : Integer;
begin
try
for I := 0 to 9 do
begin
if TTask.CurrentTask.Status = TTaskStatus.Canceled then
exit;
Sleep(1000);
if I = 2 then
raise EProgrammerNotFound.Create('Something bad just happened');
end;
if TTask.CurrentTask.Status <> TTaskStatus.Canceled then
begin
TThread.Queue(TThread.CurrentThread,
procedure
begin
if Assigned(ListBox1) then
begin
Listbox1.Items.Add('10 Seconds');
Button1.Enabled := True;
end;
end);
end;
except
on E : Exception do
begin
TThread.Queue(TThread.CurrentThread,
procedure
begin
raise E;
end);
end;
end;
end);
Task.Start;
end;
</pre>
<br />
The application is run the application and get some ugly error like this one.
"Exception TForm5.SlowProc$2$ActRec.$0$Body$3$ActRec in module Project4.exe at 00208756."<br />
<br />
The reason we don't get the correct errors is that the variable of E that is created during the during the TRY EXCEPT block is freed by the time the main thread gets around to raising the exception.<br />
<br />
So we try changing this segment of the code from this:
<br />
<pre class="brush:delphi">
TThread.Queue(TThread.CurrentThread,
procedure
begin
raise E;
end);
</pre>
to
<br />
<pre class="brush:delphi">
TThread.Synchronize(TThread.CurrentThread,
procedure
begin
raise E;
end);
</pre>
Because the Synchronize will halt the current thread and wait for the main thread to execute the the synchronized code. But we run the code and we are back to nothing happening again, but why?<br />
<br />
This is because Synchronize captures the exception and re-raises the exception in the originating thread.
<br />
<br />
<b>AcquireExceptionObject function to the rescue</b>.<br />
<br />
Calling AcquireExceptionObject allows you increment the Exception Object reference count so that it's not destroyed at the end of the TRY EXCEPT Block. Then we can call TThread.Queue and raise the exception in the main thread.<br />
<pre class="brush:delphi">
procedure TForm5.SlowProc;
begin
Task := TTask.Create( procedure
var
I : Integer;
CapturedException : Exception;
begin
try
for I := 0 to 9 do
begin
if TTask.CurrentTask.Status = TTaskStatus.Canceled then
exit;
Sleep(1000);
if I = 2 then
raise EProgrammerNotFound.Create('Something bad just happened');
end;
if TTask.CurrentTask.Status <> TTaskStatus.Canceled then
begin
TThread.Queue(TThread.CurrentThread,
procedure
begin
if Assigned(ListBox1) then
begin
Listbox1.Items.Add('10 Seconds');
Button1.Enabled := True;
end;
end);
end;
except
CapturedException := AcquireExceptionObject;
TThread.Queue(TThread.CurrentThread,
procedure
begin
if Assigned(Button1) then
Button1.Enabled := true;
raise CapturedException;
end);
end;
end);
Task.Start;
end;
</pre>
Now when something bad happens in our task the GUI is notified. Problem solved! But it's not the whole story, there are other ways to manage exceptions with TTasks, and depending on the nature of your code you this option may be better.<br />
<br />
You can remove the TRY EXCEPT Block. When a TTask is executed your user code is already wrapped in a TRY EXCEPT block, and it captures the exception for you already.<br />
<br />
If I have a reference to the Task I can call Task.Wait(TimeoutValue), which will wait for the time out for the task to complete and return true if it completed. If it has stopped executing due to an exception an EAggregateException will be raised in the thread that called Task.Wait() if that is the main thread then the user would be notified of the problem.<br />
<br />
TTask has the ability to have N number of child tasks. Because of this exceptions that are raised in a TTask are aggregated together in an EAggregateException object.
The EAggregateException is defined with the following public interface.
<br />
<pre class="brush:delphi">
EAggregateException = class(Exception)
public type
TExceptionEnumerator = class
public
function MoveNext: Boolean; inline;
property Current: Exception read GetCurrent;
end;
public
constructor Create(const AExceptionArray: array of Exception); overload;
constructor Create(const AMessage: string; const AExceptionArray: array of Exception); overload;
destructor Destroy; override;
function GetEnumerator: TExceptionEnumerator; inline;
procedure Handle(AExceptionHandlerEvent: TExceptionHandlerEvent); overload;
procedure Handle(const AExceptionHandlerProc: TExceptionHandlerProc); overload;
function ToString: string; override;
property Count: Integer read GetCount;
property InnerExceptions[Index: Integer]: Exception read GetInnerException; default;
end;
</pre>
<br />
With this interface a developer can loop through each individual exceptions, or call .ToString which places all the exception messages into a single string.<br />
<br />
Hopefully this give a few more bits of insight into exception management with threads and TTask.
<br />
<br />
<br />Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com2tag:blogger.com,1999:blog-3339459875755088113.post-40619405890883422372015-02-13T12:22:00.001-07:002015-02-15T07:18:20.872-07:00Legacy Code: What goes into a unitI found this blog post in my drafts folder from August of 2013. I think I was going to add code examples but never had the time. I guess it's better late than never, even if I don't have code examples.<br />
<br />
As a child I watched Sesame Street, and remember the "One of These Things" song.<br />
<br />
"<span style="font-family: Arial; font-size: 13px;">One of these things is not like the others,</span><br />
<span style="font-family: Arial; font-size: 13px;">One of these things just doesn't belong,</span><br />
<span style="font-family: Arial; font-size: 13px;">Can you tell which thing is not like the others</span><br />
<span style="font-family: Arial; font-size: 13px;">By the time I finish my song?"</span><br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/6b0ftfKFEJg?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
<div>
<br />
When spending time in legacy and recent code you are going to find code that mimics that song.<br />
<br />
When developing code it is best separate out distinct functionality into different units.<br />
<br />
Our system contains 80+ console applications. Each runs on a unique schedule. Such as Nightly, Monthly, Quarterly, and Annually.<br />
<br />
In our GUI application we have a factory that creates some of our screens. The factory then knows about those screens. Using this unit in one of our console applications is not needed.<br />
<br />
One day someone on my team noticed several of our console applications had dramatically increased in size. Looking at the code it was because several method were added to an existing unit that required access to the factory, although none of the console applications actually needed that code. We had to move that new method to where it belonged. <br />
<br />
When working with an existing piece of code, and you are adding functionality you need to ask does it belong. One clue to help is if you need to change the uses clause you must be aware of what you are linking not only to your unit but all the other units that use your unit. When designing new code care should be put into keeping the visual interface out of the underlying business rules. Functionality should be grouped it a way that when using unit X you are not linking code for units A, B, and C that will never be used.<br />
<br />
But now comes the problem with legacy code. You are not adding new code, your modifying the spaghetti mess that was left for you by someone else. What should you do?<br />
<ol>
<li>Attempt to understand the existing code... Sometimes this is the most difficult part.</li>
<li>If the code can be separated into two different units without changing the actual implementation details then it's far less risky to separate the units. Then all your doing is adding the new unit to the uses clause of the units that used that code where needed. Beware if your code uses RTTI this can still break things, depending on how the RTTI was used, specifically since the unit name could have been used as text either in code or an external file.</li>
<li>If separation of code can not occur without changing implementation details greater well then you need decide if it's worth it. Unlike the <a href="http://www.imdb.com/title/tt0133093/">Matrix movie</a> you get to find out how <a href="http://www.imdb.com/title/tt0133093/quotes?qt=qt0324307">deep the rabbit hole goes</a> before you take the red or blue pill. The deeper hole, the bigger the problem. Key factors I use in determining if it's worth changing the design to separate the implementation.</li>
<ul>
<li>How many places is the unit used...</li>
<ul>
<li>How many places is the unit used, directly. (i.e. in the uses clause of another unit)</li>
<li>How many places is the unit used, indirectly. (i.e. In another class you inherit from a class that was in the prior unit, then you need to find out how many places the new unit is used. This search will continue on recursively until the unit is no longer indirectly used.</li>
</ul>
<li>This allows you to answer some of these questions...</li>
<ul>
<li>How critical is this piece of code to my application?</li>
<li>How much of the application will have to be retested if I change this code?</li>
<li>What benefits do I get from changing this code?</li>
</ul>
<li>Sometimes going through this exercise I have determined what I thought was a small problem has turned into a very large problem. </li>
</ul>
</ol>
</div>
Clear <a href="http://en.wikipedia.org/wiki/Separation_of_concerns">separation of concerns</a> is critical to long term maintainability of a program. <br />
<br />
<br />
<br />
<br />
<br />Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com1tag:blogger.com,1999:blog-3339459875755088113.post-55411879864972188442015-02-12T11:34:00.001-07:002015-02-23T08:54:11.696-07:00PPL - TTask an example in how not to use.Delphi XE7 contains a new Parallel Programming Library, which is really powerful and easy to start using. But it can be something that can be done wrong, and not realize it until it's much later.<br />
<div>
<br /></div>
<div>
Lets take the following fictional example.</div>
<div>
<br /></div>
<div>
There is form with a single button and a list box. When the button is pressed a long process occurs, when the process is complete it needs to add an item to the list box.</div>
<div>
<br /></div>
<div>
This could be done without Multi-threading.</div>
<pre class="brush:delphi">
procedure TForm5.Button1Click(Sender: TObject);
begin
Button1.Enabled := False;
SlowProc;
Button1.Enabled := True;
end;
procedure TForm5.SlowProc;
begin
Sleep(10000); // simulate long process
Listbox1.Items.Add('10 Seconds');
end;
</pre>
<div>
During testing it is determined that the user needs to be able to re-size the application while the long process is running.</div>
<div>
<br /></div>
<div>
But never fail XE7 has been released with TPL and TTask to the rescue.</div>
<div>
<br /></div>
<div>
The first iteration SlowProc is changed to use a task.</div>
<pre class="brush:delphi">
procedure TForm5.SlowProc;
var
Task : ITask;
begin
Task := TTask.Create( procedure
begin
Sleep(10000); // simulate long process
Listbox1.Items.Add('10 Seconds');
end);
Task.Start;
end;
</pre>
<div>
Run the application and it appears to work. Then further testing reveals a couple of problems.</div>
<div>
The first being that button can now be pressed multiple times. The second is that if the form is closed form right after pressing the button an few seconds later and access violation occurs. </div>
<div>
<ul>
<li>The reason the button can be pressed multiple times is that the enabled is set back to true after the task is started and not </li>
<li>The cause of the access violation is that the code is still executing after the form has been freed.</li>
</ul>
</div>
<div>
The second iteration the code is now changed:</div>
<pre class="brush:delphi">
procedure TForm5.Button1Click(Sender: TObject);
begin
Button1.Enabled := False;
SlowProc;
end;
procedure TForm5.SlowProc;
var
Task : ITask;
begin
Task := TTask.Create( procedure
begin
Sleep(10000);
if Assigned(ListBox1) then
begin
Listbox1.Items.Add('10 Seconds');
Button1.Enabled := True;
end;
end);
Task.Start;
end;
</pre>
<div>
This now appears to work. But, now there can be an up to 10 second delay before the application stops running after the form closes. Now this is fictional example that has just a single sleep() call. This can occur with real world items as well, but often there are several steps in the method, so I am going to simulate multiple steps, with a loop 0..9 with a call to sleep(1000);</div>
<pre class="brush:delphi">
procedure TForm5.SlowProc;
var
Task : ITask;
begin
Task := TTask.Create( procedure
var
I : Integer;
begin
for I := 0 to 9 do
Sleep(1000);
if Assigned(ListBox1) then
begin
Listbox1.Items.Add('10 Seconds');
Button1.Enabled := True;
end;
end);
Task.Start;
end;
</pre>
<div>
Now the fictional example show multiple steps. But it does not solve the problem with the application running for up to 10 seconds after the main form is closed. When the form is begin closed the Task needs to be notified so it can stop running. This can be be done with the ITask.Cancel method.</div>
<div>
To resolve this a third iteration is produced.</div>
<div>
<br /></div>
<div>
Task : ITask; has been moved from SlowProc, and is now a member of the form.</div>
<pre class="brush:delphi">
procedure TForm5.Button1Click(Sender: TObject);
begin
Button1.Enabled := False;
SlowProc;
end;
procedure TForm5.FormDestroy(Sender: TObject);
begin
Task.Cancel;
end;
procedure TForm5.SlowProc;
begin
Task := TTask.Create( procedure
var
I : Integer;
begin
for I := 0 to 9 do
begin
if TTask.CurrentTask.Status = TTaskStatus.Canceled then
exit;
Sleep(1000);
end;
if Assigned(ListBox1) then
begin
Listbox1.Items.Add('10 Seconds');
Button1.Enabled := True;
end;
end);
Task.Start;
end;
</pre>
<div>
This all appears to work and is released. Sometime later in real world strange behaviors and errors are reported on this screen. After research it is learned that the GUI is not thread safe, so we use a TThread.Queue, to the GUI code to run in the main thread.</div>
<div>
Now onto the forth iterations of the code</div>
<pre class="brush:delphi">
procedure TForm5.SlowProc;
begin
Task := TTask.Create( procedure
var
I : Integer;
begin
for I := 0 to 9 do
begin
if TTask.CurrentTask.Status = TTaskStatus.Canceled then
exit;
Sleep(1000);
end;
if TTask.CurrentTask.Status <> TTaskStatus.Canceled then
begin
TThread.Queue(TThread.CurrentThread,
procedure
begin
if Assigned(ListBox1) then
begin
Listbox1.Items.Add('10 Seconds');
Button1.Enabled := True;
end;
end);
end;
end);
Task.Start;
end;
</pre>
<div>
Now we have an finally application that should work without error. Granted this a fictional example, but it shows just some of the pitfalls that can come with multi-threading. Each is relatively easy to deal with. </div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com11tag:blogger.com,1999:blog-3339459875755088113.post-42848225766447215172014-10-28T09:15:00.000-06:002014-10-28T09:15:39.271-06:00Introduction to GITThis week at <a href="http://www.embarcadero.com/coderage">CodeRage 9</a> I will be presenting. "Introduction to Distributed Version Control"<br />
<br />
My session covers the basics of how a Distributed Version Control System works. I focus is on <a href="http://git-scm.com/">GIT</a> but it applies to <a href="http://mercurial.selenic.com/">Mercurial - Hg</a>.<br />
<br />
Here is a <a href="https://docs.google.com/a/utah.gov/presentation/d/1J1UyrrVHMr1NhHtgZxH6Z5XiJtIwVrHqSzzZHzwJc-M/edit?usp=sharing">link to the slides</a> I used for the first 10 minutes of the presentation.<br />
<br />
I used 3 clients in the Demo.<br />
<br />
<ul>
<li><a href="http://git-scm.com/downloads">Command Line</a></li>
<li><a href="http://www.sourcetreeapp.com/">SourceTree</a> GIT/Hg Client in the Demo. </li>
<li><a href="http://www.embarcadero.com/products/rad-studio">Rad Studio XE7</a></li>
</ul>
<br />
I highly recommend learning the command line tools, there are two great demos for GIT available that I reference in the presentation.<br />
<br />
<ul>
<li>Command Line Demo - <a href="https://try.github.io/">https://try.github.io</a></li>
<li>Command Line Demo with Branching - <a href="https://pcottle.github.io/learnGitBranching/">https://pcottle.github.io/learnGitBranching/</a></li>
</ul>
<br />
What I don't cover heavily in the introduction is branching. Understanding this allows you to really leverage the power of Distributed Version Control. <a href="https://www.atlassian.com/">Atlassian</a> has a <a href="https://www.atlassian.com/git/tutorials/setting-up-a-repository">great tutorial </a>on GIT but the best part of this document is how it compares the <a href="https://www.atlassian.com/git/tutorials/comparing-workflows">various workflows</a> you could use with GIT.<br />
<br />
If your coming from <a href="https://subversion.apache.org/">SVN</a> and moving to GIT I created <a href="https://docs.google.com/document/d/168l8asmEZ0bIYARzrnuWOe5Pqfv9BExeLDhhi39X9aY/edit?usp=sharing">this cheat sheet</a> to remember the common commands.<br />
<br />
Another thing I wanted to cover but did not have time was options when it comes to hosting your git repositories that I have used.<br />
<br />
Public and Private Repositories outside your firewall:<br />
<br />
<ul>
<li><a href="https://github.com/">GitHub</a><br />Great visibility for open source projects.<br /><a href="https://github.com/pricing">Priced</a> per Private Repository, with unlimited users.<br />Public Repositories are free.</li>
<li><a href="https://bitbucket.org/">BitBucket</a><br />Good Visibility for open source projects<br /><a href="https://bitbucket.org/plans">Priced</a> per user, with unlimited repositories. 5 and under users are Free.<br />Public Repository with unlimited users are free.</li>
</ul>
<div>
I have found that I create several small repositories, and the pricing for BitBucket works well for that. So I tend to put my private repositories on BitBucket and my Public Repositories on GitHub.</div>
<div>
<br /></div>
<div>
There are several products that are designed for behind the firewall. I have only used the free <a href="http://bonobogitserver.com/">Bonobo Git Server</a>. Really want to switch to <a href="https://www.atlassian.com/software/stash">Stash</a>, but I have to wait right now due to budget limits.</div>
<div>
<br /></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com2tag:blogger.com,1999:blog-3339459875755088113.post-51726125419641523562014-09-12T10:42:00.001-06:002014-09-12T10:42:27.737-06:00VCL or FireMonkey - XE7In a <a href="http://robstechcorner.blogspot.com/2014/09/xe6-upgrade-story-now-on-to-xe7.html">previous blog</a> post I mentioned we are starting a rewrite of an existing application using <a href="http://www.embarcadero.com/products/delphi">Delphi XE7</a> . One of the comments was raised if we are going to use <a href="http://docwiki.embarcadero.com/RADStudio/XE7/en/VCL_Overview">VCL</a> or <a href="http://docwiki.embarcadero.com/RADStudio/XE7/en/FireMonkey_Application_Platform">Firemonkey</a>.<br />
<br />
It was decision we took quite seriously. Using <a href="http://www.embarcadero.com/products/delphi">Delphi</a> we spent a few days developing Firemonkey sample applications and compared them to what we could do in VCL. Firemonkey is quite nice. It has some really nice way of presenting data. However, ultimately we have decided on writing our application using the VCL. <br />
<br />
Primary reasons we to considered using VCL<br />
<ul>
<li>Existing libraries that can be reused.</li>
<li>We have written 30+ Custom Controls, that we can reuse.</li>
<li>Still maintained and enhanced.</li>
</ul>
Reasons we considered Firemonkey<br />
<ul>
<li>Can create some really pretty applications, animations, etc... that are more time consuming to create under VCL.</li>
<li>Gets most of the new features in the Delphi libraries.</li>
<li>Gives a potential to go cross platform However, we have no requirements for this.</li>
</ul>
Reasons we choose the VCL over Firemonkey.<br />
<ul>
<li>We have no need to go cross platform with this application</li>
<li>VCL applications look like the belong on windows, Firemonkey applications look like that are made to work on Windows.</li>
<li>Firemonkey is a fast moving target, and Delphi upgrades may be more difficult if we skip versions. </li>
<li>VCL is still getting improvements (But since it's mature it's not as difficult to adapt) but it's easier to upgrade between Delphi versions.</li>
<li>Existing code libraries can be reused.</li>
<li>Cost we don't have to buy or develop controls we already have.</li>
<li>Specific VCL controls - (Where we could not find a equivalent in Firemonkey)</li>
<ul>
<li>TImageScrollBox in the <a href="http://www.intervalsoftware.com/envision.html">Envision Library</a> (Really nice way to view images)</li>
<li>TRichViewEdit from the <a href="http://www.trichview.com/">TRichView</a> Library (Any RTF editor may work)</li>
<li>TTrayIcon support </li>
<li>TWebBrowser - HTML Viewing Component for desktop, we see it there for mobile.</li>
</ul>
</ul>
<div>
The good news is that XE7 supports both and I have a decision to make. I know some have said get rid of one or the other. I personally like having the choice, they each meet a different set of needs. </div>
<div>
<br /></div>
<div>
That being said part of my hope is that some of the reasons we chose VCL or Firemonkey are removed are removed in future releases. I also really want <b>supported </b>interactions that allow us to mix Firemonkey and VCL Code, such as a TFrame in VCL or Firemonkey being able to be embedded into VCL or Firemonkey form. </div>
<div>
<br /></div>
<div>
Regardless of the the framework choice, XE7 appears to be a good choice for development and<a href="http://docwiki.embarcadero.com/RADStudio/XE7/en/What's_New_in_Delphi_and_C%2B%2BBuilder_XE7"> has compelling reasons to use</a> over XE6.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com2tag:blogger.com,1999:blog-3339459875755088113.post-86046572593967714562014-09-04T16:25:00.000-06:002014-09-04T18:25:31.967-06:00Product/Component Vendors and XE7 SupportHere are the most prominent 3rd Party components(That don't ship in the <a href="http://www.embarcadero.com/products/rad-studio">Rad Studio</a>/<a href="http://www.embarcadero.com/products/delphi">Delphi</a> products) that we use. We may or may not use these in the application we will be rewriting in Delphi XE7 as we have make lots of decisions first such as VCL or Firemonkey.<br />
<br />
2 Days after XE7 was released and some people are are on top of there game.<br />
THANK YOU!<br />
<br />
The following already support XE7<br />
<br />
<ul>
<li><a href="https://github.com/project-jedi/jcl">JCL</a> </li>
<li><a href="https://github.com/project-jedi/jvcl">JVCL </a></li>
<li><a href="https://github.com/VSoftTechnologies/DUnitX">DUnitX</a></li>
<li><a href="https://github.com/VSoftTechnologies/Delphi-Mocks">Delphi.Mocks</a></li>
<li><a href="https://bitbucket.org/sglienke/spring4d">Spring4D</a></li>
<li><a href="http://www.tmssoftware.com/site/tmspack.asp">TMS Component Pack</a></li>
<li><a href="https://www.finalbuilder.com/finalbuilder">FinalBuilder</a></li>
</ul>
<div>
Patiently waiting on Support for XE7 </div>
<ul>
<li><a href="http://www.fast-report.com/en/product/fast-report-vcl-5/changes/">Fast Reports 5</a></li>
<li><a href="http://www.tmssoftware.com/site/vdsub.asp">TMS VCL Subscription </a></li>
<ul>
<li>Specifically waiting on</li>
<ul>
<li>TMS Advanced Charts</li>
<li>TMS FlexCel component Suite</li>
<li>TMS Diagram Studio</li>
</ul>
</ul>
<li><a href="http://www.tmssoftware.com/site/bipack.asp">TMS Business Subscription</a> (Waiting to purchase <g>)</g></li>
<li><a href="http://www.gurock.com/smartinspect/">SmartInspect </a></li>
<li><a href="http://www.intervalsoftware.com/envision.html">Envision Imaging Library</a></li>
</ul>
<div>
<br /></div>
<div>
I really like what TMS did for <a href="http://www.tmssoftware.com/site/radstudioxe6.asp">upgrading to XE6</a> and now they have <a href="http://www.tmssoftware.com/site/radstudioxe7.asp">done the same for XE7</a>.</div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com5tag:blogger.com,1999:blog-3339459875755088113.post-25458026060119177762014-09-03T12:26:00.001-06:002014-09-03T12:26:37.312-06:00XE6 Upgrade Story, Now on to XE7...We started the <a href="http://www.embarcadero.com/products/delphi">Delphi </a>XE6 so <a href="http://robstechcorner.blogspot.com/2014/04/delphi-xe6-easy-to-upgrade-too.html">early in the process </a>we had to convert all the 3rd party components we used to XE6 without help from the vendors. Our plan was to upgrade Delphi XE6, and move to <a href="https://www.finalbuilder.com/continua-ci">ContinuaCI</a>. We also rewrote our <a href="https://www.finalbuilder.com/finalbuilder">FinalBuilder</a> scripts from scratch, keeping in mind we would be upgrading more often. This project was scheduled to go from April and release at the end of September. We actually finished development in mid June and released after regression testing on Aug 7th. The release went really well we had <b>ONE</b> new bug reported in Production We also had less than 15 reported bugs during the development cycle. Comparing it to our last major upgrade from Delphi 2007 to XE we were over schedule, we lost count on the number development bugs, and we had many more problems in production. <br />
Testing our application suite takes apx 1.5 months to complete. Due to the time it takes to completely retest the application we tend to have to isolate areas and focus on them for release. This allows us to have faster testing time as we don't have to as thoroughly test all areas. A luxury we don't get when upgrading Delphi as all area of the code need to be retested.<br />
<br />
Because testing time is such a major part of development, we have been slowly but surely increasing the number of of unit tests. We also have some research going on in <a href="http://en.wikipedia.org/wiki/List_of_GUI_testing_tools">GUI Automation Tools</a>, but we are not pleased with our current options here. We are also researching adding GUI testing to <a href="https://github.com/VSoftTechnologies/DUnitX">DUnitX</a>. Each has benefits and drawbacks that are obvious and others that we will only find out by trying.<br />
<br />
That being said our team will not be able to upgrade our whole product suite to XE7 as 3 months of QA time a year to do Delphi Upgrades is too costly. So we will have to wait for XE8 and maybe even XE9 for our whole product suite to be upgraded. <br />
<br />
That being said XE7 still appears to is a <a href="http://docwiki.embarcadero.com/RADStudio/XE7/en/What's_New_in_Delphi_and_C%2B%2BBuilder_XE7">very compelling upgrade</a>.<br />
<br />
Our very first Delphi application that was developed here (long before I arrived) is showing it's age, it was originally developed in Delphi 3. It came complete with every bad programming practice I have ever seen. Global variables, events containing all the business logic, the worst being it's desire to use hidden TEdit as variables. Granted it was the first Delphi application written by that team, and they were learning the language on this project.... But it's just not worth trying to fix. Not to mention that the business has evolved and wants something different that what it did.<br />
<br />
The last version of Delphi that will touch this application is XE6. <br />
<br />
Today we are starting a project that will rewrite this application, were we will be using XE7. <br />
<br />
<br />
<br />
<br />
<br />Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com2tag:blogger.com,1999:blog-3339459875755088113.post-81163056758885907602014-05-06T10:59:00.000-06:002014-05-06T10:59:42.018-06:00Support and how it should work.During our XE to XE6 upgrade project, we felt it was time to redo our build process.<br />
<br />
We are using <a href="http://www.finalbuilder.com/finalbuilder">FinalBuilder</a> and <a href="http://www.finalbuilder.com/continua-ci">ContinuaCI</a> produced by VSoft Technologies in Canberra, Australia.<br />
<br />
During the process we ran into some minor bugs, in the product. We also had some major and minor feature requests. <br />
<br />
Anytime I ran into one of these, I would shoot off an email to the product support email address. <br />
<br />
Sending an email to them would result in a automatic Ticket Number response email from the <a href="https://www.fogcreek.com/fogbugz/">FogBugz </a>software they are using. I don't know much about FogBugz, but as customer I love the interaction and being able to see the status of the emailed ticket at any time.<br />
<br />
Then after sending the email, I would then leave for the day, the next morning I would come in and have a response to my ticket. <br />
<br />
What made me happy about these responses was most of the time they contained a link to a build with a fix to the problem I was experiencing. If I had made a minor feature request, that commonly was also implemented in the same time period. For major feature requests, I was informed that the request was placed on the list to implement, some times with follow up questions to ensure they knew what I was asking for.<br />
<br />
Typical response time for a bug fix: < 24 hours. <br />
Longest I remember waiting on a bug fix < 2 weeks.<br />
<br />
As a customer I have never felt my opinion or bug was under valued or should be discounted because of some other mitigating factor. A behavior I commonly get from other companies. <br />
<br />
I could be getting lucky with my requests, but I highly doubt it as we have seen this behavior several times over the years we have been using their products. I am sure sooner or later something nasty will come up that will take longer, but I know it won't just be sidelined, it will be worked on, and I will be kept informed of what is going on.<br />
<br />
My point is, VSoft Technologies really has support covered. I wish other companies, I work with had that level of support. Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com6tag:blogger.com,1999:blog-3339459875755088113.post-63715914417127951492014-04-18T13:19:00.002-06:002014-04-18T13:19:45.622-06:00XE6 - New Look and FeelOne of the first things long time Delphi Developers may notice about XE6 is that it has new look and feel.<br />
<br />
One thing I have learned over the years is that when you change the user interface in any way you will get a divergent number of opinions. My opinion of this change is simple: I like it.<br />
<br />
I have made two similar screenshots of XE5 and XE6, so you can compare the differences.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbYn_g9eih5gD9Cp8A4TpP2v40ODanJ11upw2XGdok2o3rvHoZw0-OoejBYoGFDjX9mIsJasIgPxXKMg_zdTqUDLXGn0YCEeT9DwtOe1y-S2nk4eawZ8Qf-ceApaQg-DIrpuPYYk9Fu2Ct/s1600/XE5LookAndFeel.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbYn_g9eih5gD9Cp8A4TpP2v40ODanJ11upw2XGdok2o3rvHoZw0-OoejBYoGFDjX9mIsJasIgPxXKMg_zdTqUDLXGn0YCEeT9DwtOe1y-S2nk4eawZ8Qf-ceApaQg-DIrpuPYYk9Fu2Ct/s1600/XE5LookAndFeel.JPG" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD_DWRFf1JPVS4xhrpo9lD-AYiU-6aGPg8GkwPZP_dnikXMrC26MkiwaATwlQfwZ15YdJc4aWuQCzevYXq6vw_kpOq9f419YdNOK4jx11jyBopI2XQ-yesjzIqc0GLk8hSs0xVKMswxw1D/s1600/XE6NewLookAndFeel.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD_DWRFf1JPVS4xhrpo9lD-AYiU-6aGPg8GkwPZP_dnikXMrC26MkiwaATwlQfwZ15YdJc4aWuQCzevYXq6vw_kpOq9f419YdNOK4jx11jyBopI2XQ-yesjzIqc0GLk8hSs0xVKMswxw1D/s1600/XE6NewLookAndFeel.jpg" /></a></div>
<br />Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com4tag:blogger.com,1999:blog-3339459875755088113.post-26793751692721481052014-04-16T17:03:00.000-06:002014-04-16T17:07:08.993-06:00Delphi XE6 - Easy to upgradeDelphi XE6 was just released yesterday! My team of 10 Delphi Developers has been moving fast.<br />
<br />
Several Open Source Libraries that my team uses have been updated to support XE6. <br />
<br />
<ul>
<li><a href="https://github.com/VSoftTechnologies/DUnitX">DUnitX</a></li>
<li><a href="https://github.com/VSoftTechnologies/Delphi-Mocks">Delphi-Mocks</a></li>
<li><a href="https://github.com/project-jedi/jcl">JCL</a></li>
<li><a href="https://github.com/project-jedi/jvcl">JVCL</a> </li>
<li><a href="https://bitbucket.org/sglienke/spring4d">Spring4D</a></li>
<li>We also updated <a href="https://code.google.com/p/omnithreadlibrary">OmniThreadLibrary</a> but don't know how to submit changes back for that but all we did was created XE6 packages from the prior version it worked fine.</li>
</ul>
<div>
We were able to internally update our commercial libraries such as TMS, SmartInspect, Envision, RichView, FastReports and few others because we did not want to wait. The latest version of FinalBuilder already supports XE6 so that made our build easy.</div>
<div>
<br /></div>
<div>
We now have our primary application working with XE6. It was quite easy to do. </div>
<div>
<br /></div>
<div>
Our code base is over 2 million lines of code. We have 178 Packages (all have been converted) We have 650+ DPR, several of these have been converted. Finishing all of the secondary applications (DPR's) right now, and expect to have our conversion complete in the next 3 weeks. </div>
<div>
<br /></div>
<div>
This has been a <b>VERY EASY </b>upgrade. We were upgrading from Delphi XE.</div>
<div>
<br /></div>
<div>
I had some headaches with the license registration, but once you get past that the product works well.</div>
<div>
<br /></div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com5tag:blogger.com,1999:blog-3339459875755088113.post-33695765667973115182014-02-17T11:05:00.000-07:002014-02-17T18:05:49.802-07:00pfSense - Network PerformanceI am lucky enough to live in an area where I can get a <a href="http://www.sumofiber.com/residential_internet">fiber connection to my home</a>. <br />
I pay for 100 GB and 100 GB down. However, I was never able to achieve this performance levels. About a year ago I took a bandwidth speed test. This is what I was able to get get. My wife was on the phone (VOIP) at the time and my kids were watching Netflix. So I had competing traffic.<br />
<div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.speedtest.net/result/2625856939.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://www.speedtest.net/result/2625856939.png" /></a></div>
</div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
At home I have been using a <a href="http://www.dlink.com/us/en/home-solutions/connect/routers/dir-665-xtreme-n-450-dual-band-gigabit-router">Dlink 665 Router </a>for a long time, and it worked for my needs. <br />
<br />
But then I wanted to do the following<br />
<ul>
<li> Block all DNS Query traffic that is not going to "<a href="http://www.opendns.com/home-internet-security/parental-controls/opendns-home-vip/">Approved</a>" DNS Servers.</li>
<li> VPN into my home network.</li>
<li> Monitor bandwidth by device on my network.</li>
</ul>
I have been researching options on what could provide provide these, including:<br />
<ul>
<li>Devices</li>
<li>Aftermarket firmware for existing devices.</li>
<li>Using Linux or FreeBSD and spending hours configuring it.</li>
</ul>
<div>
After not having much luck finding something that would meet my needs, in my price range.<br />
asked a co-worker what he used. He pointed me to <a href="http://www.pfsense.org/">pfSense</a>. </div>
<div>
<br /></div>
<div>
pfSense is a Open Source Firewall based on FreeBSD.</div>
<div>
<br />
I add a second NIC to an older spare machine I had. Then I installed pfSense, it was a very easy to install. I had it running with the base configuration, a few minutes after inserting the CD and starting the install. </div>
<div>
<br />
I then spent a few hours to get it configured as desired, but it was really easy. Most of the time was spend readdressing my home network, as I desired a more structured ip address layout compared to random undocumented method that I had before.<br />
<br /></div>
<div>
<div>
I expected to get the features I was after, but one took me by surprise.<br />
I noticed our connection seemed much faster than before. <br />
<br />
So I took another speed test, I had my son watch Netflix like he was before. <br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.speedtest.net/result/3312632134.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://www.speedtest.net/result/3312632134.png" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Wow! <br />
<br />
Granted lots of things could have changed in a years time. So some of the differences may not be attributable to pfSense. However, I am not about to install the Dlink 665 again to find out out the true differences.<br />
<br />
But since I noticed the improvement, without the speed test, I thought I should post a glowing review of <a href="http://www.pfsense.org/">pfSense</a>. All of the features I wanted have been working really well, and it has more feature than I will ever need, allowing me to expand to meet my needs.<br />
<br />
If you need need a better firewall at the your home or office. It's worth looking into <a href="http://www.pfsense.org/">pfSense</a>.<br />
<br />
<br />
<br />
<br /></div>
</div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com9tag:blogger.com,1999:blog-3339459875755088113.post-25201267450837830732013-12-30T14:44:00.000-07:002014-01-05T17:59:39.197-07:00DUnitX and my plansI have been a big fan of using unit testing frameworks. I use both <a href="http://dunit.sourceforge.net/">DUnit </a>and <a href="https://github.com/VSoftTechnologies/DUnitX">DUnitX</a> for my Delphi tests.<br />
<br />
I am right now contributing to DUnitX as I see it as the future framework of choice for Delphi Developers. <br />
<br />
I just wanted to talk in public about some of work I have going on around DUnitX. My goal is simple to get feedback from the Delphi community.<br />
<br />
<h2>
IDE Expert</h2>
It is really easy to setup a test project and test fixtures with DUnitX, but I thought it could be easier.<br />
<br />
So I created a new Delphi Open Tools Expert that does the following:<br />
<br />
<ul>
<li>File | New | Other | Delphi Projects | DUnitX Project</li>
<ul>
<li>Creates a new DPR/DPROJ</li>
<li>DPR Source is modeled after the DUnitX example unit tests.</li>
<li>Base Project Search Path set to $(DUnitX)</li>
<li>Optionally creates a Test Unit</li>
</ul>
<li>File | New | Other | Delphi Files | DUnitx Unit</li>
<ul>
<li>Creates new Delphi unit</li>
<li>Adds DUnitX.TestFramework to uses</li>
<li>Creates a new class with correct attributes, you get to specify class name</li>
<li>Optionally creates Setup and TearDown methods</li>
<li>Optionally creates Sample Test Methods.</li>
<li>Registers the TestFixture in the initialization section.</li>
</ul>
</ul>
<div>
Basically it's not much, but it provides a framework to reduce your time to get to writing actual test code. I am nearly done with this code, I wrote most of it during the Christmas Break. Hopefully in the next week I can finish this. It's going to take some time, as I have to build a machine with Delphi 2010 through XE5 on it to test this functionality as I only have XE and XE5 installed right now.<br />
<br />
<strike>To see the current state of the code check out this <a href="https://github.com/rlove/DUnitX/tree/expert">expert branch</a>. </strike><br />
<b>Update:</b> Code is now part of the <a href="https://github.com/VSoftTechnologies/DUnitX">master branch on the Main Project</a><br />
<br /></div>
<h2>
Data Driven Test Cases</h2>
<div>
<br />
The potential to have data driven test cases is the main reason why I started looking at DUnitX. </div>
<pre class="brush: delphi"> [TestFixture]
TMyTestObject = class(TObject)
public
[Setup]
procedure Setup;
[TearDown]
procedure TearDown;
// Sample Methods
// Simple single Test
[Test]
procedure Test1;
// Test with TestCase Atribute to supply parameters.
[Test]
[TestCase('TestA','1,2')]
[TestCase('TestB','3,4')]
procedure Test2(const AValue1 : Integer;const AValue2 : Integer);
end;
</pre>
<br />
The method <b>Test2</b> above shows up as two different tests, the first time it's called with 1 and and second time it's called with 3 and 4.<br />
<br />
I recently <a href="https://github.com/VSoftTechnologies/DUnitX/commit/eb41c8bcd0e71dec23c166158d36c3ec8bf2005d">made a change</a> to underlying structure of the code. First I created a new record called TestCaseInfo followed by two new abstract attribute classes<br />
<br />
<br />
<pre class="brush: delphi">
/// <summary>
/// Internal Structure used for those implementing CustomTestCase or
/// CustomTestCaseSource descendants.
/// </summary>
TestCaseInfo = record
/// <summary>
/// Name of the Test Case
/// </summary>
Name : string;
/// <summary>
/// Values that will be passed to the method being tested.
/// </summary>
Values : TValueArray;
end;
TestCaseInfoArray = array of TestCaseInfo;
/// <summary>
/// Base class for all Test Case Attributes.
/// </summary>
/// <remarks>
/// Class is abstract and should never be, used to annotate a class as a
/// attribute. Instead use a descendant, that implements the GetCaseInfo
/// method.
/// </remarks>
CustomTestCaseAttribute = class abstract(TCustomAttribute)
protected
function GetCaseInfo : TestCaseInfo; virtual; abstract;
public
property CaseInfo : TestCaseInfo read GetCaseInfo;
end;
/// <summary>
/// Base class for all Test Case Source Attributes.
/// </summary>
/// <remarks>
/// <para>
/// Class is abstract and should never be, used to annotate a class as a
/// attribute. Instead use a descendant, that implements the
/// GetCaseInfoArray method.
/// </para>
/// <para>
/// Note: If a method is annotated with a decendant of
/// TestCaseSourceAttribute and returns an empty TestCaseInfoArray, then
/// no test will be shown for the method.
/// </para>
/// </remarks>
CustomTestCaseSourceAttribute = class abstract(TCustomAttribute)
protected
function GetCaseInfoArray : TestCaseInfoArray; virtual; abstract;
public
property CaseInfoArray : TestCaseInfoArray read GetCaseInfoArray;
end;
</pre>
<br />
With these two classes, I changed <b>TestCaseAttribute</b> to descend from <b>CustomTestCaseAttribute. </b><br />
Then I changed the architecture to create a Test based on the <b>TestCaseInfo </b>record structure, that is obtained by either the <b>CaseInfo </b>or the <b>CaseInfoArray </b>properties of the abstract classes.<br />
<br />
This little change provides for some really nice functionality, for example I have working sample that uses FireDAC to provide the
values to my tests method<br />
<br />
<pre class="brush: delphi"> FireDacTestCaseAttribute = class(CustomTestCaseSourceAttribute)
protected
FTestName : String;
FConnectionName : String;
FSelectStatement : String;
function GetCaseInfoArray : TestCaseInfoArray; override;
public
constructor Create(const ATestName : String;const AConnectionName : String; const ASelectStatement : String);
end;
// Which then can be used like this:
[FireDacTestCase('TestName','MyDBConn','select strVal, IntVal from Table');
procedure MyTestMethod(AValue1 : String; AValue2 : Integer);
// Right now the test come out names 'TestName1', 'TestName2', 'TestName3' although that will
// change before I commit my code to allow specifying values.
//Most likely passing the TValuesArray with a Format call on testName like this:
[FireDacTestCase('TestName%0:s%1:s','MyDBConn','select strVal, IntVal from Table');
procedure MyTestMethod(AValue1 : String; AValue2 : Integer);
</pre>
<br />
This attribute is not in the <b>DUnitX.TestFramework.pas</b> to avoiding creating dependencies on those that don't use this functionality. This needs quite a bit of work before it's polished enough for general use, but it's what I am working on next after the expert is submitted as a pull request. <br />
<br />
Note: Since FireDac changed it's naming, I believe it might be XE4 or XE5 specific.<br />
<br />
<br />
<h2>
Repeat Attribute</h2>
<br />
DUnitX defines a <b>RepeatAttribute </b>that is currently not implemented. I made an attempt at implementing it, and I don't like it. If anyone has better idea, I would be happy to entertain it.<br />
<br />
Otherwise, I have some small improvements I think I will make and will submit it again.<br />
<br />
My implementation can be found in <a href="https://github.com/VSoftTechnologies/DUnitX/pull/26">Pull Request #26</a> which won't auto merge due another change being implemented first, but can be viewed in a working state in my <a href="https://github.com/rlove/DUnitX/tree/RepeatAttribute">RepeatAttribute branch</a>.<br />
<br />
<h2>
Future Plans</h2>
Things I want see in a Unit Testing framework is vast, I not sure what I will start on next but here are some areas I am considering with no preference on order. Note: this is not a road map as some may never be done (at least by me)<br />
<br />
<ul>
<li><a href="http://www.nunit.org/index.php?p=category&r=2.2">Test Categories similar to NUnit</a> as I have 10k+ of DUnit tests currently and categories might make it easier to group run on the ones I am interested in.</li>
<li>VCL and Firemonkey GUI Runner</li>
<ul>
<li>Understands and can filter on categories</li>
<li>Quick Filter by name</li>
<li>Run all or specified tests</li>
<li>Simplify the DUnitX project source and make easier to select which runner is used.</li>
<ul>
<li>VCL</li>
<li>Firemonkey</li>
<li>Console</li>
</ul>
</ul>
<li>Something similar to GUITesting.pas found in DUnit</li>
<li>Load and run tests stored in BPLs.</li>
<li>Data Driven Tests Enhancements</li>
<ul>
<li>dbExpress</li>
<li>CSV Test Case Source</li>
<li>XML Test Case Source</li>
<li>TestCaseSource Attribute</li>
<ul>
<li>IOC looks up the Test Case Source Builder Interface</li>
<li>Other Sources implement Test Case Builder Interface and Register it in IOC Container.</li>
</ul>
</ul>
<li>Remote Test Framework</li>
<ul>
<li>Think mobile, tests are on the device the runner is on your development machine.</li>
<li>Think Test Farm, multiple machines, with different configurations all running tests.</li>
</ul>
<li>Implement TestInOwnThreadAttribute </li>
<li>Find better way to test new functionality in DUnitX.</li>
</ul>
<h2>
Thank you</h2>
<div>
And last but not least I would like to thank <a href="http://www.finalbuilder.com/Resources/Blogs/author/vincent-parrett/">Vincent Parrett</a> and his team for the set of great tools he as produced for the Delphi community.</div>
<div>
<br /></div>
<div>
I use the following:</div>
<div>
<ul>
<li><a href="http://www.finalbuilder.com/finalbuilder.aspx">FinalBuilder</a> - Build Automation Tool - Commercial - Well worth the price!!!!</li>
<li><a href="http://www.finalbuilder.com/continua-ci.aspx">ContinuaCI</a> - Build Server - Commercial - Free single for a single build server/agent.</li>
<li><a href="https://github.com/VSoftTechnologies/DUnitX">DUnitX</a> - Unit Testing Framework - Open Source</li>
<li><a href="https://github.com/VSoftTechnologies/Delphi-Mocks">Delphi-Mocks</a> - Mocking Framework - Open Source</li>
<li><a href="https://github.com/VSoftTechnologies/DUnit-XML">DUnit-XML</a> - DUnit XML output in NUnit Style - Open Source</li>
</ul>
<div>
There is more Open Source he has produced all <a href="https://github.com/VSoftTechnologies">listed on GitHub</a>.</div>
</div>
<br />
<br />
<br />
<br />Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com12tag:blogger.com,1999:blog-3339459875755088113.post-60889490381240847792013-10-08T10:47:00.000-06:002013-10-08T10:47:22.278-06:00CodeRage - Next Week Next week is CodeRage, I am looking forward to speaking again.<br />
<br />
I have two sessions:<br />
<br />
<ul>
<li>A VCL Developers Guide to Firemonkey</li>
<ul>
<li>October 15, 2013 @ 8:00 AM PDT</li>
<li>This session is for those VCL developers who want to learn Firemonkey but have never taken a dive in. Designed to help these developers save time by addressing the difference in a quick and easy way.</li>
</ul>
<li>Responsive Delphi Design</li>
<ul>
<li>October 16, 2013 @ 1:00 PM PDT</li>
<li>Now with mobile developer we are faced with multiple form factors (Device Sizes). How do we create a single application that looks good on each form factor you</li>
</ul>
</ul>
<div>
Attendance is FREE and online, all you need to do is <a href="http://forms.embarcadero.com/CodeRage8Registration">Register before the 15th</a>.</div>
<div>
<br /></div>
Robert Lovehttp://www.blogger.com/profile/09035581266678763273noreply@blogger.com0