Re: pseudo-specs for a String class

From: Kinkie <gkinkie_at_gmail.com>
Date: Tue, 2 Sep 2008 07:12:56 +0200

Thanks for this extra feedback. I appreciate the advice everyone is giving.
I'll have limited access to the net for the next couple of days so I
won't be able to answer to the points you make right away, I should
have the time to incorporate some of your suggestions by then.
 Are you!

On 9/2/08, Alex Rousskov <rousskov_at_measurement-factory.com> wrote:
> On Tue, 2008-09-02 at 05:10 +0200, Kinkie wrote:
>> On Tue, Sep 2, 2008 at 12:21 AM, Alex Rousskov
>> <rousskov_at_measurement-factory.com> wrote:
>> > On Sun, 2008-08-31 at 14:07 +0200, Kinkie wrote:
>> >
>> >> I've gotten a bit forward, now I'm a bit at a loss about where to go
>> >> next.
>> >
>> > I would move string, stream, and other formatting functions away from
>> > this class.
>> >
>> > I would move searching and comparison functions away from this class.
>> >
>> > I would probably remove default conversion from char*. It buys you very
>> > little in Squid low-level Buffer context, but can introduce serious
>> > problems (we have seen some of that during the previous BetterString
>> > attempts).
>>
>> I'm trying to make the class as useable as possible.
>> Subclassing to add those operations is of course a possibility, I
>> invite you to check the code out (it has a quite rich test/example
>> section).
>
> Test/examples do not matter in this particular case. What matters is the
> unexpected and expensive implicit conversions that are pretty much
> guaranteed to appear in the real code if implicit conversion from char*
> is allowed. We cannot avoid all implicit conversions, but I would still
> recommend removing the implicit conversion from char* from any
> buffering- or string-related class.
>
>> >> char *exportCopy(void);
>> >> char *exportRefIKnowWhatImDoing(void);
>> >
>> > What do these return and how do they differ?
>>
>> The first exports a copy of the KBuf contents (potentially expensive
>> but clear from the point of view of memory management), the latter
>> exports a reference to the internal storage. Very cheap but quite
>> dangerous as the underlying storage may be moved away. Thus the name
>> expresses a contract by which the caller declaares to know what she's
>> doing.
>
> Understood. Please document:
>
> - the mechanism for destroying/freeing a "safe" copy,
> - whether the "safe" copy is null-terminated,
> - the scope where it is safe to use the IKnowWhatImDoing reference.
>
>> >> KBuf& operator = (char const *S, u_int32_t Ssize);
>> >
>> > Does C++ have a tertiary assignment operator?
>>
>> of course not; please conosider that interface is a mock-up. Actual
>> functions are:
>>
>> assign(KBuf &)
>> operator = (KBuf &)
>> assign (const char*, size_t)
>> assign (const char*)
>> operator = (const char *)
>
> OK. The conversion from char* string and lack of "const" comments apply
> to all of these but the third one then.
>
>> >> const int operator [] (int pos);
>> >
>> > Useless without size() and probably does not belong to a low-level
>> > buffer.
>>
>> size() has been implemented since.
>> That operator returns -1 (EOF) on out-of-bounds. I agree it's probably
>> useless, I'm know of throwing all possible ideas in, removing calls is
>> always possible.
>
> I agree that removing something is always possible. On the other hand,
> reviewing "all possible ideas" APIs is painful and not very productive.
> Also, it is usually easier to add than to remove.
>
>> > There are a few places with methods arguments are references that are
>> > missing "const". Please review.
>>
>> Ok. Are you referring to the mockup or did you check the actual code?
>
> I am referring to the "Current interface" blob you posted, asking about
> the direction to go next. If the actual interface is not the "current
> interface", please post whatever we should be looking at.
>
>
> Four more comments on the "current interface" blob. Sorry if these are
> irrelevant to the actual work.
>
> * Please document the results of invalid operations such as appending
> more data than would fit or truncating more than there is. I would
> recommend throwing an exception as the starting point, but whatever the
> final/agreed solution is it needs to be documented and discussed.
>
> * bool isNull();
>
> Unlike for a pointer, being "null" is a strange state for a buffer.
> Please consider renaming that method to isEmpty (if that is what you
> meant). BTW, MemBuf::isNull is not isEmpty!
>
> * KBuf nextToken(const char *delim); //strtok()
>
> The above API would require removing the token from the object or
> keeping the token pointer as additional data member. Neither approach
> allows multiple concurrent string iterations. Is that intentional?
> Should data iteration be external to the object holding the data?
>
> * Many methods that probably do not modify the object are missing
> "const" at the end.
>
>
>> As already discussed, I have no objections to splitting the class'
>> interface in low-level and high-level.
>> I'm currently taking the pragmatic approach that the high-level
>> functions going to be almost always used anyways, so might as well
>> clump them together.
>
> Not sure why clumping high- and low-level interfaces together is
> pragmatic, but when do you expect to make the decision on whether the
> final interface you recommend would be "clumped" or not? This decision
> would affect a few key aspects of String/buffer classes, such as
> construction and extraction, so it would be nice not to delay it for too
> long.
>
> Thank you,
>
> Alex.
>
>
>

-- 
    /kinkie
Received on Tue Sep 02 2008 - 05:12:59 MDT

This archive was generated by hypermail 2.2.0 : Tue Sep 02 2008 - 12:00:02 MDT