Re: Discovering variable types...

From: Bjørge Sæther (bjorge_at_hahaha_itte.no)
Date: 08/16/04


Date: Mon, 16 Aug 2004 19:10:18 +0200

Marco van de Voort wrote:
> On 2004-08-13, Bjørge Sæther <bjorge@hahaha_itte.no> wrote:
>> Bad OOP, yes. It can really be a nightmare.
>
> Yes, but also gray OOP (so not good or bad) should be avoided. If OOP
> has
> no advantage, don't use it (since it might turn into bad oop).

Why is that ? Should I develop different programming styles to fit different
kinds of projects ? I'd better use my efforts to keep the code (and the
model) clean.
The problem is more that of not trying to be a smartie when a more
rudimentary solution will make it better. When one tries to pack too much
functionality into polymorphic classes to avoid any 'case' - statements, one
may end up with a really complex code. When classes are central to the
solution, one should not use the black-box approach unless this simplifies
things.
An example of mine from yesterday: I had this really simple dataset class,
written in an hour or so, but having made it into several of my projects.
After modifying the classes in two different projects, meeting different
needs, I found it was really time to merge these versions. Then I ran into
problems like having stored a list of integers in one version and a list of
objects in the other. I remember that the idea "avoid the objects - keep it
simple" made me use integer arrays instead of the list of object references
l would normally use. The pragmatic non-OO approach got me into extra work.
I don't do this anymore, as I know these things are harder to remember at
some later stage.

>> I do not *only* write OO code. But - once I recognize a pattern like
>> "hmmm...all these routines concern a data structure ilke
>> this...hmmm", then the conclusion may be: "...I'll turn it into a
>> class !". Typically, when a group of routines take a data structure
>> as a parameter, it's a good case for OO. IMHO ;-)
>
> Depends on the case. A data structure may be part of a larger buffer,
> or written directly to disk.

I never do that. I don't think I'll ever do that. I'd have to move tro
another profession, I guess. Not because it's wrong, but I normally use at
least one level of "abstraction" between my data and the disk. But this has
been discussed thorouhly lately, I guess...In concequence, I usually have
data placed in structures that to me seem to fit nicely into objects.

>>>> You don't have* to use polymorphism or any of that nasty stuff...
>>>
>>> What's the point then?
>>
>> The other things - data and code together.
>
> Like a unit :-)

Nope. That's the difference. The code is not *together* with data just
because it's declared in the same unit.

  MyData.AsInteger:=10;
  Caption:='And this is the data presented as a string: '+MyData.AsString;

...can't be done without OOP. It has nothing to do with polymorphism, it's
as useful when written in a standardized way for a number of different
classes. Like the .Count property or method of any list-like class - you
just know it's there. No problem creating the function

  function Count(Arr: TMyArray): integer;

...only that

  MyArr.Count;

...is much neater than

  Count(MyArray);

...as the latter one has to be read kind of backwards to give the whole
picture (much like german syntax to a non-german, the verb at the end)

>> initialization & finalization
>
> Yes. However this works well when the subject models well with OOP.

Not necessarily *well*, it just has to be done no matter what style you're
on. Better place it where you don't have to think about it all the time,
then. I believe I get your point, though, as it may be a problem e.g. to
make a class "re-entrant" when it was originally written for doing
operations only once per execution. Like my mentioned "easy-dataset", it was
originally written to be filled once and never altered afterwards.
Destruction would work, but not inserting or deleting records, as the
initialization stuff wasn't generic. Takes a bit more work to do that
properly.

>> routines. "InstanceSize", "ClassName", "RTTI", "Messaging",
>
> Hardly use these.

I use RTTI all the time. Messaging only as a last resort, to desperately
avoid coupling. ;-)
I've used ClassName from time to time, to be able to register & find classes
much like in classes.pas.

>> "Interfaces",
>
> Would maybe use them more, if not reference counted. Now rarely use
> them.

Agreed. This should not be mandatory. I've used them for avoiding a few
lines of code, though...but this is more fun than very important. Especially
as many Delphi coders are not used to them and would hence scratch their
heads over the vast number of orphaned objects ;-)

>> "TStringList", "TList".
>
> Use only for prototyping. Too much problems with scaling. (insertion
> above
> a few ten thousands objects becomes _slow_, even on 2 GHz)

Have you ever seen the 'Capacity' property ?
Insertion is of course doomed to be slow if you don't insert them at the
end.

>> Oh, yes. In a one-class-one-unit style of units, yes.
>
> Has nothing to do with it.

Of course it has. When you start with the unit name, you get all available
symbols of that unit in your Code Completion list. To make it as tidy as
with classes, you need to group routines in very specific units. Otherwise
you have a lot to choose from, many of them totally irrelevant. Then one
solution could be prefixing the routines after the kind of parameters they
work on (as mentioned a few blocks down).
I do also have libraries of flat routines, and I find them more easily
messed up if I am not careful. Especially going back one year later, being
*almost* sure I've already written the one I need....but what is it named ?

> Class = scope with identifiers.
> unit = scope with identifiers.
>
> If you don't use double level qualifiers (quala.qualb.identifier) by
> default, units can be used for the same thing.

But I like being feeling free to use a few large units instead of a lot of
small ones.
They're here with .NET, I guess. And I don't like that. I do not like using
unit names for qualifiers, for the same reason I find global variables
making harder to read the code...and a unit name may be taken for a global
variable & vice versa.

>> My units typically have a number of classes, and they would normally
>> have routines for more than one specific parameter type. I see
>> programmers use procedure names like "Int_XXXX" to solve part of
>> this, the parallell to Java-style "Integer.XXX". It's just a matter
>> of preferences, but I believe I'm not the only one finding OOP
>> cleaner at this point.
>
> I don't get this?!?

Have you seen the advanced SQL tools with popups like in Delphi ? Their main
problem is that if you start writing:

  SELECT
    ...then you won't have any possibility of "code completion" popping up
relevant fields because the table/view or whatever you're gonna select from
isn't yet specified. If the form was

  FROM
    MYTABLE
  SELECT
    ..then I would have a list of relevant fields popping up here.

I don't want a myriad of units, as OOP allows me to group functionality
within one unit. There are limits to this, of course, and from time to time
I refactor to split things up a bit.
Also, when it's not obvious what the routine may do and what kind of
parameters it does it to, I find naming harder on flat routines. Names tend
to grow longer.
It doesn't matter for other than "style", and I would certainly not claim
that the application is better when written with OOP. But I find myself
quite intensively avoiding using "passive" structures like records and
arrays. But that's me, growing up with OOP.

> If one had open array unstructured array of byte, one could omit the
> size parameter if it was equal to the size of the passed value.

Yes. Like "compiler magic OOP". Not a bad idea ;-)

>> I have never come to miss being able to read the actual variable
>> size, though, even if it could save a few lines of code in the
>> stream stuff.
>
> It avoids typo's.

Sure.

>> But if it was to be *really* useful, you'd need the data type as well
>> (much like with variants).
>
> Not really. That is totally different functionality.

Related, though. We're talking about passing untyped data.

> This is a mapping of a var of a type to memory (either real memory or
> disk) like abstraction. Type is not needed.

As I said, IMHO. I often need to be able to know the type of a "generic"
data chunk, more than the size. So, my point was - if Delphi was to be
modified at this point, I'd like to be able to read the type as well. Now
this info is available only for variants, const parameters and published
class properties. I have used this functionality for all of these. While the
size would require 4 bytes, the type would require only 1. As CPU speed /
RAM size increases, we could certainly use a few bytes'n ticks to have this
info.

-- 
Regards,
Bjørge Sæther
bjorge@haha_itte.no
-------------------------------------
I'll not spend any money on American Software products
until armed forces are out of Iraq.


Relevant Pages

  • Re: Public Variables
    ... If you wanted to really follow the OOP paradigm, ... > Are you stating that I should ALWAYS declare ALL variables as private? ... > My object is not to learn programming style as I only wrote this one ... >>> The program consists of 2 forms, and about 12 routines I wrote. ...
    (microsoft.public.dotnet.languages.vb)
  • Re: Discovering variable types...
    ... Bad OOP, yes. ... "hmmm...all these routines concern a data structure ilke this...hmmm", ... Hmm, maybe if I switch to OOP context: ...
    (comp.lang.pascal.delphi.misc)
  • Re: Using Classes
    ... Obviously there was a learning curve but I have a programing ... I know that Python is very OOP friendly, but I could not figure out ... In essence, instead of letting general routines awkwardly and error-prone choose the right type-specific routines depending on the object, let the object specify ...
    (comp.lang.python)
  • Re: an old geezer running visual studio for the first time
    ... Maybe your idea of OOP is not as complete as it can be. ... sounds more like componentization than OOP in general. ... functionality is in a common base class. ... > closing rapidly the connetion again) and only change data by way of SQL ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: Classes functions....help!
    ... You need to study up on object-oriented programming, ... If you don't understand OOP, ... A class is simply a container for functionality and data. ... functionality of the class which it inherits. ...
    (microsoft.public.dotnet.framework.aspnet)