Filetype help

On the forums someone is looking for a way to identify what kind of file they are dealing with. And then a way to “sort” knowing those types.

The suggestion given is to look at each extension in a simple way

But, you can get away without ever having to look at the extension. Folderitem already assigns a TYPE IF there is a filetype defined that matches.

You can use this built in ability to do many things.

I posted about this on INN along with a sample project

Help keep your code sanity

Ever think to yourself “Oh I have this project to do and I’ll just cut and paste the code from there and tweak it?” And now you have two copies that are a lot alike but maybe not exactly the same.

And then you do this over & over and now you have many copies of that code?

How do you deal with issues when you find them ?

Which copy is the newest & the most correct ? And which one is the right good copy to use as the basis for yet another copy ?

I’ll admit that I will copy & paste code to examine it. Play with it to see how it breaks. And then I throw it away and fix the real single working copy that IS the master for all others.

And there are some neat tools for this like Snippets for BitBucket Server

Copy & paste coding is fast. Repetitive. And it has issues. Which is why copy-paste programming is used mostly as a negative comment on coding style.

And it can be dangerous

If you have the ability to avoid it by using submodules, includes, sub-projects in whatever version control system you’re using (you ARE using version control right?), or similar mechanisms I’d encourage you to do so.

It will help you avoid the proliferation of many different versions of the same code in all your projects.

And when you need to fix the code you can fix one copy and all your other projects can be updated with it.

Labelling

A long time ago I was in a BEd\Bsc program at University.

It was supposed to end with me having two degrees. One Degree in Education and one in Computer Science. But the two faculties couldn’t agree on the course of studies over 5 years. And when I got to year 5 it turned out both expected me to do at least one more full year in each faculty. I wasnt financially in a position to do that and had to decide which to finish. Since I had more credits towards my BSc at that point I finished that. But I did have the better part of 3 years of a BEd under my belt as well.

One of the things that came up for discussion during that education was “labels” and how they affect not only the person(s) being labelled, but also the person who applied the label. If you thought of a kid as “slow” or “stupid” or some other negative term, then you, as their teacher, were more likely to react and treat them in accordance with those labels. And you could inadvertently contribute to that child being treated as “slow” or “stupid”. How you perceived them had a direct impact on how you treated them.

If instead you thought of this student as “smart” and “capable” that too could factor in to how you treated those students.

The best defence was to realize when you were doing this and ACTIVELY work to combat doing this. (This article is VERY good on what to do and how to avoid it)

This sort of thing occurs a lot. We probably all do it from time to time. We label people in various ways. Kind. Considerate. Jerk. A-hole. You name it.

The trouble with applying such labels is that once they are applied they tend to stick. And this assumes that whatever behaviour was labelled is permanent, unchangeable and fixed for all time.

A single clumsy attempt at a joke could end up getting a person labelled as a jerk. And the person applying that label remembers that forever and treats that person as “a jerk” from then on. And never bothers to attempt to ever see that person they labelled in any other way. They were “a jerk”. They are “a jerk”. They always will be “a jerk”. Period.

The trouble is that it’s not realistic. People can in one moment be jerks, and in another extremely considerate, caring and compassionate. Rarely are people ALWAYS some singular label. People ARE complex and labels are often too simplistic. Especially if they are applied rigidly and NEVER re-examined to see if the reasons we labelled that person that way. Re-examination is hard because its very likely we base that re-examination ON the labels we have already applied.

The other downside to labels is that the person applying the label can use that label to dismiss the other person. Whether its complaints, concerns, or whatever its easy to see how labelling someone a jerk leads to “so I dont have to listen to them or try to understand their concerns – they’re jerks !”

And since “they’re jerks” everything is seen through that lens. Reasonable criticisms are seen as “Its by that jerk so I dont have to listen or even try to see IF they have some legitimate reason for that criticism. They’re jerks !”

I’ll admit that I do get frustrated with people and complain about them.
Esp as I drive (ask my wife) I do try to avoid labelling people – but its not a 100% success rate.

And, to be honest, I expect that the people this post is meant for might not read it.
Because they have applied a label which they feel gives them permission to ignore this.
Because that single fixed label that requires no thought, no reexamination, or consideration of anything that other person says, thinks, or does.

Coincidence

Sometimes you want classes to have a common API.

But rather than adding a common super class or interface to define that common API, you just make sure your classes have the same methods, events, properties & whatever else you feel is necessary to make them have “the same API”.

I would suggest you rethink doing this.

If what you need is controls that are similar but have differences in them just making it so you have common methods names, properties, and events will make trying to write any common code that can manipulate these controls a pain in the read end to create, maintain, and update.

For instance, lets suppose we create two controls that do wildly different things. One is a canvas control subclass that draws itself in whatever color set with a blue frame. The other draws the frame in in red. (This example is exceeding simple just to illustrate the issues. Its worse with more complex classes & controls)

So we have

Class BlueCanvas
  Inherits Canvas

  property myfillColor as color

  Sub SetFill(newFillColor as Color)
     myfillcolor = newFillColor
  End Sub

  Function GetFill() as Color
     return myfillColor
  End Function

  Event Paint(g as graphics, areas() as 
     g.forecolor = myfillColor
     g.fillrect 0,0, g.width, g.height

     g.forecolor = &c0000FF
     g.drawrect 0,0, g.width, g.height
  End event
End Class

Class RedCanvas
  Inherits Canvas

  property myfillColor as color

  Sub SetFill(newFillColor as Color)
     myfillcolor = newFillColor
  End Sub

  Function GetFill() as Color
     return myfillColor
  End Function

  Event Paint(g as graphics, areas() as 
     g.forecolor = myfillColor
     g.fillrect 0,0, g.width, g.height

     g.forecolor = &cFF0000
     g.drawrect 0,0, g.width, g.height
  End event
End Class

So our two controls have “the same API”

Same events, same methods, same properties of the same type & name.

Lets see what happens when we try to write code that uses these two simple controls.

Suppose we’d like to write a single method that can change the fillcolor of either control

Sub AlterFillColor(ctrl as Variant)

   Dim c As Color 

   If SelectColor(c,"select a color") Then
  
    If ctrl IsA BlueCanvas Then
      BlueCanvas(ctrl).myFillColor = c
      BlueCanvas(ctrl).Invalidate
    Elseif ctrl IsA RedCanvas Then
      RedCanvas(ctrl).myFillColor = c
      RedCanvas(ctrl).Invalidate
    End If
  
End If

Note several things. The parameter passed in has to be something generic – but it cant be a BlueControl or a RedControl as there is nothing really common between them. We could pass a Canvas but that would not change the code in actual method.

We MUST check to see, in this case, exactly what type was passed in because we cant be sure an appropriate type was passed in. Even if we used a Canvas we’d have to check because a generic Canvas may not have the myFillColor property and trying to access that would cause compilation errors. If we use Variant anything can be passed in. If we make that parameter an Object any INSTANCE of ANY class, not JUST our labels, can be passed in.

We MUST cast, either one time and assign to a temporary we reuse , or on every line of code where we use the control.

And this is one VERY short method and it already looks messy.

How about adding a button to copy the value of myFillColor from one canvas to another.

If we add one button to copy from the bluecanvas to the redcanvas, and another to copy the other way we can copy directly from one to another using something like :

RedCanvas1.SetFill( BlueCanvas1.GetFill() )

or

BlueCanvas1.SetFill( RedCanvas1.GetFill() )

This isnt so bad. But, being the clever sort we are we decide to write a generic “copy from one to the other” method and reuse the heck out of it (and this is where your spidey sense should really go crazy !)

Public Sub CopyFill(fromCtrl as variant, toCtrl as Variant)

  Dim copycolor As Color

  If fromCtrl IsA BlueCanvas Then
    copycolor = bluecanvas(fromctrl).FillColor
  Elseif fromCtrl IsA redCanvas Then
    copycolor = redcanvas(fromctrl).FillColor
  End If

  If toCtrl IsA BlueCanvas Then
    bluecanvas(toCtrl).FillColor = copycolor
  Elseif toCtrl IsA redCanvas Then
    redcanvas(toCtrl).FillColor = copyColor
  End If
  
End Sub

And from the outset we have the same issue as above

Except now to manipulate two items we need to do several checks to see what types the from and to controls are.

So despite these “having the same API” thats of no real value since you have to cast and check all the time. And your parameters to methods have to be some more generic type like variant or some common super that still leaves you needing to cast all the time.

Worst of all you can pass ANY parameter that is of the right type. The compiler cannot help you check that your code is correct since it cant do type checking.

Now what if we decide we want to add a … YellowCanvas !

You can go back and see for yourself how many places we have to adjust to handle this “new” type. Every place we have a cast is a potential place we need to add code to.

And every place we add code is a new place for new bugs to crop up.

So how can we solve this in our little example ? I’m sure many of you have already seen the answer. In this case an interface ISNT of use since we can’t define events and properties.

But a common base class, even one that CANNOT be created directly, is of use.

Class FramedCanvas
  Inherits Canvas

 property myfillColor as color

  Sub SetFill(newFillColor as Color)
     myfillcolor = newFillColor
  End Sub

  Function GetFill() as Color
     return myfillColor
  End Function

  Private Sub Constructor()
    // makes it so you cant place instances on a layout
    // or create them direcly
  End Sub

End Class

Class BlueCanvas
  Inherits FramedCanvas

  Event Paint(g as graphics, areas() as 
     g.forecolor = myfillColor
     g.fillrect 0,0, g.width, g.height

     g.forecolor = &c0000FF
     g.drawrect 0,0, g.width, g.height
  End event
End Class

Class RedCanvas
  Inherits FramedCanvas
  
  Event Paint(g as graphics, areas() as 
     g.forecolor = myfillColor
     g.fillrect 0,0, g.width, g.height

     g.forecolor = &cFF0000
     g.drawrect 0,0, g.width, g.height
  End event
End Class

Now our classes dont just have the same API because we happened to write them that way. They have the same API by definition. They cant NOT have the same API.

Now our method to set a fillColor looks like

Public Sub AlterFillColor(ctrl as FramedCanvas)
  Dim c As Color 
  
  If SelectColor(c,"select a color") Then
    
    ctrl.FillColor = c
    ctrl.Invalidate
  End If
  
End Sub

Note we CAN use the super class as the TYPE for the parameter. BlueCanvases are also FramedCanvases. As are RedCanvases. But a regular canvas control could NOT be passed in (unlike before) and we do not need to do any casting etc. The compiler CAN check for us what is passed in. So our reliability and likelihood of writing bug free code is improved.

And, note, we have LESS code than before. And even if we add YellowCanvases etc we do NOT need to alter this code. Thats a good thing.

Directly copying the fill color from one control to another still works about the same

BlueCanvas1.SetFill( RedCanvas1.GetFill() )
BlueCanvas1.Invalidate

or

RedCanvas1.SetFill( BlueCanvas1.GetFill() )
RedCanvas1.Invalidate

What about our method based copy that we want to just reuse like mad ?

Public Sub CopyFill(fromCtrl as FramedCanvas, toCtrl as FramedCanvas)
  toCtrl.FillColor = fromCtrl.fillColor 
End Sub

Its trivial. No casts. No need to alter it every time a new sub type of framedCanvas comes along. And unlikely to ever have a bug.

Why ? Because these controls have an EXPLICIT API that forces them to be the same. Its not just because I happened to write the same code in several of them but because BY DEFINITION they are the same.

Where’s this all leading ?
Well so far this has all been simple and in a desktop app. It could just as well have been in a web app, iOS or some other app type. But the PRINCIPLES hold true even if you wanted to extend this to be across all those app types.

Suppose the hierarchy defined was

  Control
     - common control events, method & properties

     RectControl
         - common rect control events, method & properties 
           (for controls bound by a bounding box)
         Button
            - common button events properties & methods
            DesktopButton
               - events properties & methods specific to the desktop
            WebButton
               - events properties & methods specific to the web
            iOSButton
               - events properties & methods specific to ios            
         Canvas
         Listbox
         TabPanel
         PagePanel

and so on

Now its plausible to write a method that regardless of whether it was used in a desktop, ios, or web project that could locate a Control, Rectcontrol, or Button. Or any other control that is defined.

No casting required.

There are some compatibility details. The DesktopButton would have to have its flags set to only be in desktop projects, the web ones only in web projects, etc. That would solve trying to compile a desktop project with iOS or web controls & vice versa.

The same may be true for controls that only exist on the desktop, and have no counter parts elsewhere. But those flags can be set at any level in the hierarchy.

And the IDE could check those flags to see what things ARE compatible and not allow you to use ones that arent.

The other upside with a properly laid out hierarchy like this for EVERYTHING is that it BY DEFINITION it tells you what properties you could expect to carry over if you copied a desktop button and pasted it into a web project. Nothing that is desktop specific should, or could, make sense in the web one. But anything defined in BUTTON and higher up in the hierarchy would, or should, be able to be copied over to a web button when you paste.

Currently its hard for any of us to do this in a cross platform app that targets ios, web and desktop simply because the underlying items in the frameworks do not do this already.

And the IDE doesnt seem to sort things out right. Depending on what version of the IDE you use you might see in the example SameXPLATExplicitAPI that the Blue Canvas has its compat flags all off but thats really wrong since it SHOULD be compatible with desktop. It would be subclassed from the Desktop one. And using those modules on ios would be from the IOS one. And on web from the web one. But this doesnt work as I expect. In some versions they are all greyed out and things “run” but the paint events never get called 🙁

So trying to make a FramedCanvas, like above, that works in iOS, desktop, and web IS, at the moment, not possible.

Making it so things share as much of their API by DEFINITION rather than just by coincidence would make it so more code is, or can be, cross platform without needing to copy paste from project to project.

Imagine THAT world !

Examples

When extension methods aren’t a suitable replacement

A lot of API 2 is extension methods that are replacements for the classic global framework methods.

String.LowerCase is for all intents and purposes the equivalent of Lowercase(string).

Except when its not.

If you happen to have methods that can return a wide variety of types you may not be able to use the extension methods.

For instance if you have something like

Function Foo(NameOfTypeToReturn as string) as Variant
     // this code IS just for illustration purposes !
     select case nameOfTypeToReturn
       case "String"
           return "string"
       case "Double"
           return 1.234
       case "Integer"
           return 99 // yeah that many red balloons !
       else
           return nil
       end if
End Function

and you were to try and do

Dim s As String

s = Foo("Double").Lowercase

s = Lowercase(Foo("Double"))

only one of these will compile. It’s NOT the extension method style.

And it makes perfect sense why not.

An extension method has a specific signature.

Lowercase is defined like

Function Lowercase(extends str as string) as String

essentially for this to MATCH the parameter to it has to already BE a string. But the return value from Foo is a variant – that can be turned into a string – but isnt already a string. So that usage “doesnt match”. An dyou get a compilation error.

The second however will accept something that can be turned into a string. Which a variant can do. So it compiles just fine.

WinUI

Recently there was a blog post about Xojo looking at WinUI as the new foundation for Xojo.
Thats great – except (you knew that was coming didnt you?)
WinUI wont support anything older than Windows 10 at this time (specifically they note Win10, 1809+)
How Xojo handles this will be interesting to watch.

Will they simply abandon Win32 and any users on older versions ? I could see that happening as it would be similar to what happens with old versions of macOS. Then to support old Windows versions you have to use an old version of Xojo.

It may be irrelevant since Windows 7 support officially ended in 2020.

Hopefully MS can ship WinUI as planned and Xojo apps on Windows will get a whole new look and maybe even new controls

http://feedback.xojo.com/case/61410

Misunderstanding the issue

Last night I read a blog by someone who obviously misunderstands why it is INN and some inhabitants are disheartened by where Xojo is at this point.

There are some there who are definitely Xojo haters now. They didnt start out that way. Years of “it’s coming soon” have lead them to not believe those statements. “Show me” has become their mantra. It’s not real until it ships and everything before that should be ignored.

The IDEA of Xojo is truly wonderful – a tool that can tackle many targets & platforms with a consistent language and reasonably similar frameworks for each target. There are going to be differences and especially differences in behaviour – the web being what it is latency is an issue. Mobile/touch devices dont normally support the same kinds of UI operations as desktop does since there are no mouse or other desktop like input devices – usually. So there will be differences.

And many of those denizens on INN DO still continue to use Xojo. Not all. But many.

But INN’s purpose is to focus on cross platform development – so it has topics on different tools (B4J, Java, RemObject, Swift) that Xojo will not permit on their forums. And it does have uncensored commentary on Xojo itself. Again something that Xojo does not permit.

There ARE comparisons to other tools – primarily for those looking to expand their horizons in any direction (ie/ moving to Xojo from Java or moving to Java from Xojo) The languages are similar in so many respects that moving from one to the other is not difficult. And neither is likely a perfect replacement for the other in all cases.

Good cooks , like good carpenters, use many tools and dont try & use one tool for everything. It doesnt usually work if you try to make everything in the microwave. It doesnt all need the same power settings, the same cook time, nor does it all fit. The same is true for carpenters, Try to use a single tool for everything doesnt work well. Hammers make lousy saws, and saw make lousy hammers.

Being able to mix and match the right tool for the right job requires knowing how to use other tools. And, often, such comparisons or discussions about those other tools are not permitted on Xojo’s forums.

INN exists for all these reasons.

So yes you may get unbridled boosterism for some favourite tool – like Xojo or Java or RemObjects or Swift. But you can & will get other perspectives.

Me ?

I still say to people that I use Xojo and post code that uses it. I still like the IDEA of Xojo. And I’ve used it for so long I can bang out something pretty quickly. I do run into issues. I’ve filed some 600+ feature & bug reports and just keep on moving.

I just happen to dislike where Xojo is at today.
I’m allowed to have an opinion 🙂

Deploying Web Apps

I know Xojo just wrote one but to be honest I really like this one

This handy tool makes it so dead easy its crazy.

Even if you just hacve a static web site its dead simple

LifeBoat should be called life saver

Simple. Fast. Not expensive and does what it does without any muss or fuss.

And it looks good doing it.

If you build web apps

Of just about any kind, not just Xojo web apps, LifeBoat is so darned handy you really should get it.

Its so easy to use that today I redeployed a web app several times in a matter of minutes.

Its truly one of those must have tools

Web 2.0 thoughts

Lately I’ve been writing a Web2.0 app and TBH I can see where folks are experiencing issues.

There are omissions, glitches and bugs that need addressing.

But, I also wonder why Xojo hasnt dog fooded Web 2 with Feedback or some other app they use and rely on ? And that would show them the issues developers are facing.

!5 years ago, before I ever joined REAL, they decided to write the IDE using the IDE. Something they hadnt been doing. A practice known as dogfooding.
And from my decade working there I can say that it helped make things easier to see when a user submitted a bug report. And there were a lot of bugs that never went out the door because we used the IDE to write the IDE.

It was a good idea to do this because

The engineers who are developing REALbasic are now having an experience more in line with their customers’ own experience, which gives them a better sense of what does and doesn’t work.

https://www.macworld.com/article/174461/realbasic-45.html

I do wish they’d write something like a web version of Feedback using Web 2. And, if thats not possible then work to make it possible. Feedback doesn’t have that complex a UI (does it?) It should be possible and if its not maybe that says exactly how ready Web 2 is ? It certainly says something about its readiness.

Your thoughts ?