Replies: 4 comments 6 replies
-
Hm, that would be quite a lot of changes at once 😉 Although I don't see any problems with the removal of the deprecated options and the As you know, I'm not a fan of having an object just for the sake of it. I prefer so-called pure functions. So I really like the design of the " But as far as I understand it, you would want to drop this design in Java/Kotlin in favor of the " Well, I'm not sure I agree with that since I am using static functions in Java all the time. And Kotlin even has top-level functions, which I use extensively, too. So I wouldn't say everything needs to be OO in Java or Kotlin. And the same is true for iOS, to some extent. Swift also has top-level functions, and you can, of course, have static functions in Objective-C, too. So for me, the " My concern is that in the long run it doesn't make much sense to offer two ways of doing the same thing, mainly because there is no significant advantage of one approach over the other 😬 |
Beta Was this translation helpful? Give feedback.
-
Working on the writing part and contemplating the (a)symmetries between reading and writing, I came to the conclusion that taking the OO approach one step further and going full fluent interface style looks even more worthwhile and 'right' to me. With the plan to make
This makes 'writing' symmetric to 'reading', as they both transform back and forth between an So the current model symmetric to auto text = "Hello";
auto creatorOpts = CreatorOptions(BarcodeFormat::QRCode).setEcLevel("50%").setQuietZones(true);
auto barcode = CreateBarcodeFromTetx(text, creatorOpts);
auto writerOpts = WriterOptions().sizeHint(400).withQuietZones().withHRT().rotate(0);
auto image = WriteBarcodeToImage(barcode, writerOpts); Note: This is already 'semi' fluent with respect to the creation of the using BarcodeFormat;
auto svg = Create(QRCode).withECLevel("50%").withQuietZones().fromText(text).asSVG(); or if we'd want to reuse the builder/creator: auto createQRCode = Create(QRCode).withECLevel("50%").withQuietZones().rotatedBy(90).asGS1();
for (var text : inputs)
std::cout << createQRCode.fromText(text).asSVG() << "\n"; This would also lend itself quite nicely in case we wanted to be explicit about the input, like Just to give an idea how this could then look for the reader side: using BarcodeFormat;
auto iv = ImageView(...);
auto barcodes = Read(LinearCodes)
.with(Binarizer::FixedThreshold)
.with(TextMode::Plain)
.withErrors()
.withMinLineCount(3)
.withSymbolLimit(2)
.skipRotate()
.fast()
.from(iv);
// std::optional<Barcode> ReadPure::from()
auto pureBarcode = ReadPure(Pdf417).from(iv).value(); Notes:
Any suggestions with some motivation why this looks like a good/bad idea are welcome. EDIT: updated the options naming of the writer part according to currently implemented experimental API. |
Beta Was this translation helpful? Give feedback.
-
Discounting CC-C composites (which use GS1-specific modified PDF417s),
there are only 3 GS1-approved symbologies that can have ECIs, all matrix,
namely GS1 Data Matrix, GS1 QR Code and GS1 DotCode.
Only for the last 2 are ECIs explicitly not supported (GS1 General
Specifications v24 Section 5.7.3 QR Code, Section 5.8.2 DotCode).
However, given that none of the allowed character sets can contain anything
other than subsets of ASCII, ECIs are useless anyway, and the lack of an
explicit statement about GS1 Data Matrix is probably just an omission.
GS1 have in the last few years introduced certain AIs, to do with transport
process (postal addresses), that specify using percent-encoding (RFC 3986)
for non-Latin characters (see Section 2.6.15).
Zint merely returns a warning if ECIs are used with GS1 data, for all 3 GS1
matrix symbologies, only returning an error if non-ASCII (or non-printable
ASCII) characters are used.
It also merely returns a warning if printable ASCII characters outside the
allowed GS1 character sets are used.
Re the fluent interface, I'm not really qualified to have an opinion. Are
errors not allowed? That would seem difficult to enforce...
…On Mon, Feb 26, 2024 at 10:56 AM axxel ***@***.***> wrote:
Question for the encoding expert in the room ***@***.***
<https://github.com/gitlost>): The zint API seems to imply that GS1
symbols (across all symbologies) can only ever contain "text", meaning ECI
899 can not be part of it. Can a GS1 symbol contain any ECI segment at all?
In the above outlined fluent interface design I can imagine using either
of the following approaches:
- something like asGS1() flag as in the example above, but that would
allow calling fromBinary()
- add a fromGS1(string) function, but that would allow setting a
withECI(ECI) parameter
- providing a separate CreateGS1(BarcodeFormat) factory that would not
support setting any ECI/binary data, encoding this restriction in the type
instead of throwing an error if configured inconsistently.
—
Reply to this email directly, view it on GitHub
<#724 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADVVPR5H4IIHVTOTDZXAILYVRS5FAVCNFSM6AAAAABDJ7OO5CVHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM4DKOJQHE3TQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
A functional, object oriented or fluent API are all fine to me. Object oriented API seems to me the most standard C++ approach. I prefer keeping backwards compatibility as much as possible. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Working on the 3 most recent wrapper efforts (Rust, .NET, Kotlin/Native) made me realize that the
ReaderOptions
+BarcodeReader
based API of some of the older wrappers is suboptimal / inconsistent.Quick history recap: I replaced the overly complicated public API that was inherited from Java with the most trivial one I could think of: a single function call
ReadBarcode(image)
with some optionalReaderOptions
. I saw no value in requiring to first instantiate someReader
object, only to then execute that read-function. That is still valid. But then came the wrapper subject where e.g. in Java or C# is it 100% idiomatic to model this not as a (static class) function but in an OO way.Now I believe I was shortsighted when I decided to go with the
BarcodeReader
in Android+iOS but kept the separateReaderOptions
at the same time. That separation is superficial and adds no value but rather noise to the API. Bottom line: I'd like to change that and make sure each API/wrapper offers one (or both) of the following designs:ReadBarcodes
function +ReaderOptions
structBarcodeReader
class with all the options as properties, plus aBarcodes read(ImageView)
functionJust in case that is not obvious:
BarcodeReader
is simplyReaderOptions
with aread()
function that passesthis
as theoptions
argument to the underlying c++ call.They may happily coexist in some environments (like C++) but others may choose to offer just one depending on the most natural approach of the platform (like Python, C, Android). And
BarcodeReader
may actually be derived fromReaderOptions
, like in the .NET wrapper.Since @markusfisch and @benjohnde are the most invested and contributed enormously to the Android and iOS code, what would you say if I went ahead with this backward incompatible change? I would then obviously do the full removal of the 3 deprecated options plus the
Result
->Barcode
renaming in the same release.EDIT: for an extended discussion of the
fluent
part of the title, see belowBeta Was this translation helpful? Give feedback.
All reactions