About Attributes

From 2011 to late in 2013, I worked in Delphi XE, exclusively, and for the last 5 months, I have been working in Delphi 2007. Now, however, I am on the brink of leaping forward to Delphi XE5. Compared to D2007, The changes are very large, indeed:

  • Unicode
  • Generics
  • Attributes
  • Live Bindings

I have already been accustomed to the shift to Unicode, from working in XE. Similarly, I did make use of generics in XE, though not extensively. Attributes and Live Bindings, on the other hand, are uncharted territory.

I expect to dive first into attributes, and suspect they may help me to deal with some currently thorny problems. I say suspect, as I am still mainly scratching my head over how attributes can and should be used. Attributes can be applied to many types in Delphi, as seen in this article. But the mere fact that they can be applied to something does not mean that they should be. My slowly increasing understanding of them–some features simply elude my comprehension for a time, until I see a compelling example, then the light goes on–includes an appreciation of two important considerations:

  1. Making use of attributes requires using RTTI, which brings with it significant performance penalties, so if performance is an issue, it may be best to avoid their use.
  2. Using attributes provides late binding, which in turn means that the compiler cannot protect us from our own stupidity: if we misuse attributes, then we may run afoul of run-time errors.

One challenge is that in numerous examples, all too often the use of the attributes seems to be almost a bit of magic. Not being a fan of clever code, I hope to avoid using them in ways which make the code less comprehensible.

More later, as I find something worth demonstrating in code.

Categories: Attributes

A small adventure in RTF

I have need of fixing the RTF comments contained in some 48,000 records in a database. These were imported from another database some years ago, and the original data is no longer available. The import process damaged at least some of them, generally by copying into a too small container, thus truncating the RTF script. On my form, I have placed a TMemo (memPlain) and a TRichEdit (memRich). I fill them with this code:

procedure TfrmMain.FillMemoes;
var
  str: TMemoryStream;
  s: string;
begin
  str := TMemoryStream.Create;
  try
    s := dsLookup.DataSet.FieldByName( 'vComment' ).AsString;
    Label2.Caption := s;
    memPlain.Lines.Text := s;
    str.Write( PChar( s )^, Length( s ) );
    str.Position := 0;
    memRich.Lines.LoadFromStream( str );
  finally
    str.Free;
  end;
  if not chkDisableRepairs.Checked then
    MakeRepairs;
end;

The MakeRepairs procedure is simple:

function TfrmMain.MakeRepairs: Boolean;
begin
  Result := False;
  if CheckPlainAndFix then
    Exit( True );
  if CleanRTFAndFix then
    Exit( True );
end;

A little function to make things a bit less cluttered:

function TfrmMain.HasRTFDelims(const text: string): Boolean;
begin
  Result := ( PosEx( '{', text ) > 0 ) or
  ( PosEx( '}', text ) > 0 ) or
  ( PosEx( '\', text ) > 0 ) ;
end;

At this point, I must say that I had gotten ahead of myself. I wound up abandoning CheckPlainAndFix, and instead added some visual tools to let me learn about the actual problems in the data. What I learned changed my direction entirely.

There are 48,799 records in the database. Of these, it turned out that RTF was damaged in 59 of them. Annoying, but a much smaller incidence of problems than my client thought existed. My suggestion was that I could simply manually correct these few, and save the updates. It made little or no sense to code a solution, both because so few records were involved, and because among that small number, there were several different pathologies observed, at least one of which would have required a good deal of experimentation to resolve.

My client countered with the decision that we would make no repairs. These data are a few years old. It may be that the users will never open them, and as the reporting from the app is done for only the current year, they will have no impact there.

Lessons (re)learned:

  1. Next time I am told that we “have a big problem” I shall go no further than to measure the actual magnitude of the problem.
  2. Coding any sort of fix, however minor, for any sort of encoded stream prior to completing step 1 is just silly.

Those points are pretty fundamental, and I had certainly learned them years ago. But in this case, my client told mew a) that the damage was widespread and b) that he had tried to apply some repairs in SQL, but will little success. That said to me that he had done some analysis, and that it was a substantial problem in need of a clean solution. However, as I tripped over issues in debugging my code, I began moving toward trying to quantify the problem, and if necessary, to quantify the categories of pathologies, in terms of the difficulty it might involve to code a repair. With a total of only 59 damaged records, very little coding would have been justified.

In the final analysis, the only routines with value in my little project were:

  1. The small routine which recognized RTF delimiters in the visible text of the TRichEdit.
  2. The code I added to count the number of damaged records.
  3. The visual items added which let me see the list of damaged records and click on each ID to reload the TRichEdit, allowing very rapid determination of pathologies.

Therefore, I have not developed any sort of RTF code repair tool. The need may surface someday, or I may decide to pursue it on my own, for the experience, but my client has no need of it.

On the other hand, one of the discoveries I did make was that a very small number of users had copied and pasted from Word to the app which originally managed the data. As might have been anticipated, Word exports in RTF (just as it does in HTML) a rather large number of elements which it would be nice to remove. Dozens of RGB color specifiers, for example. Now that may well be a project for me do undertake at some point. Even in the records affected in this way, the colors had not been used, so there is no reason whatever to retain them. It is just MS-bloat.

Categories: Uncategorized

Shifting priorities

I’ve been quiet for months. Much of my work has been afflicted with the challenge of overcoming breaking changes in third-party products which are pervasive in my apps. Not much fun, and as the project is finally winding down, so is my stamina. I need a change.

I’ve just acquired a Raspberry Pi, on my way to getting an irrigation system installed at my home. I was originally looking at an AVR based controller, but now, from the same vendor, I have the option of an add-on card to the Raspbery Pi to fulfill the same requirements.

Honestly, I thought this over for weeks. First, we’ve had so much rain this year that it’s not urgent to get a system installed–but I know it will be needed, soon enough. But second,  I have been an AVR fan for years, and it was initially attractive to have a controller based on an AVR. However, the more I thought about it, the more I was drawn to the Raspberry Pi solution. 

Both products are open source, but the AVR version is using Arduino, which would not be my first choice. the Raspberry Pi version controller is written in Python, also not high on my list, but as RPi is a Linux machine, and many languages are available for it, I have the option of designing my own controller, in C, C++, or Pascal, as I decide.

Further, I have no desire to deal with TCP/IP on the AVR. It may actually be well shielded from the user by the Arduino approach, but at best, this is a niche solution. The RPi on Linux follows a more general path.

As I said above, I have received my RPi, but as I have not yet had time to do more than look at it, I have little to say so far. In my next articles, I expect to document the process of getting it operational, and getting a development environment in place. More to come….

Categories: Uncategorized Tags: ,

Frameworks, everywhere… and no documentation

Even as many claim that Delphi is on the wane, we see more and more open source frameworks cropping up. Large or small, they all being something to the table, and some are very powerful. All have been created in response to a perceived need, necessity being the mother of invention.

Unfortunately, one characteristic most of them share is a lack of documentation. It is all well and good to believe that you write self-documenting code, but it is best to remember that you are, after all, immersed in the work you are doing, so of course, once you are there, it seems obvious.

To many of the rest of us, it is far less obvious. Write comments, at the very least. Better yet, write actual documentation. It is becoming a lost art. And if or when you do write documentation, don’t be a syntax fanatic in your code and dismissive of syntax in your writing. They are of equal importance.

You may write a framework that none of us should be without, but if we can’t quickly get a sense of why it exits and how to use it, many of us will simply turn away, as we don’t need yet another hobby, or worse, a science project.

Categories: Docs Tags: , ,

Just another software blog…

So, I needed a place to store articles, and had not used WordPress before. Who knows where this may lead? Settle back, and enjoy the ride.

Categories: Uncategorized

A COM Rant

COM. To know it is to love/hate it.

From COM we gain the ability to access tools in a language-agnostic way. In-process or out-of-process servers, servers running as services, servers which provide the interface to exotic hardware. In theory, it’s great. In practice, it can be very frustrating.

Vendors: Just because you publish a COM interface doesn’t mean you’re done. In fact, COM tends to be in greater need of documentation than many other technologies. Sample applications can help, but they also will be written in a programming language which may not be the one your customer prefers. We all know you won’t write the apps in multiple languages—even though this would be a terrific method of enhancing the documentation—and no sample app will ever obviate the need for a manual which presents the design philosophy. Even a single line of information about each method call is better than none.

Developers: Just because you have toughed your way through numerous adventures with ill-conceived and undocumented interfaces is no reason to put up with more of the same. Agitate for documentation, where none is given, or for better, where some exists.

An aside: Why is it that so few developers, despite living in a world where syntax is everything, and compilers utterly unforgiving, give so little attention to the quality of their prose? In documentation, as in code, syntax matters! Clarity is essential. A compiler may put up with spaghetti code, but most readers will soon tire of misspelled words, ambiguous and incorrect antecedents, disagreement of number, and confused tense.

It has been my experience that projects using COM are invariably plagued with confusion at the front end, and although they usually resolve well in the end, the cost in time, money, and frustration is larger than with more traditional solutions. As I am at the front end of such a project now, wrestling with wholly inadequate documentation, insufficient sample applications, and no documentation of design philosophy, I will have more to say. Stay tuned….

Categories: COM