Agreed, I can't even find the original problem easily. A 20 page thread is no place for code golf. I altered the problem because it seemed like that's what was currently trendy: framing the problem in a way so that the "wrong" person's approach would have issues.
Originally Posted by techgnome
Huh... I noticed the conversation has moved away from VB6-v-VB.NET to a more broader subject of Battle of the Design Patterns. Perhaps that's really the crux of the issue, not one of actual languages but the patterns and habits we use.
-tg
The thing I don't like about dueling patterns, as fun an opportunity to show off as it is, is it perpetuates the myth that there's a "right" answer. It's particularly bad when you pit two different languages against each other, because the APIs and patterns and idioms that work well in one might not be so elegant in the other. For example, writing my post with an early version of C# that lacked delegates would mean losing a lot of my cooler tricks.
So I got sucked in. I was bored, and having a beer with a lot of time to kill.
I feel like this is where we sit in the discussion:
"Here's my solution in VB6, it uses patterns A and B and I plan to extend it this way."
"I kind of like solving it this way in VB .NET, I can use patterns C and D to do the same thing."
"Ugh, no, you don't NEED OO code for this, I did it just fine with A and B."
"Whatever, patterns C and D are well-known and get the job done. Patterns A and B are known to have these problems, it's in plenty of texts."
"No, patterns A and B are perfect, it's C and D that have the problems. Please explain how you'd solve <intentionally bad C&D scenario> with C and D."
This is kind of the point where person 2 ought to roll their eyes and move on. VB6 has some weak spots and there will be problems it just can't solve in an elegant manner. VB .NET also has weak spots, and there will be tasks it fails at that VB6 can tackle elegantly. There's no really good general-purpose language that exceeds at all tasks, the best we can get is one that's great at some things and good at most. It is very possible that both people are right, are using perfectly fine approaches to the problem in their language, and would be up the unsanitary tributary if they tried that approach in the other person's language.
We mustn't get insulted when someone thinks another approach is better. If they're technically wrong, you can comment on that, but it doesn't need to be a "won" argument. Later, someone reading the thread can see a proposal->rebuttal->counterargument discussion and decide for themselves what is best for their solution. Heck, for almost every problem we've discussed I can come up with a scenario where the "good" advice is totally wrong. We need to know all solutions, with all their upsides and downsides, to make the best decisions based on our information, schedule, and budget.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
Agreed, I can't even find the original problem easily. A 20 page thread is no place for code golf. I altered the problem because it seemed like that's what was currently trendy: framing the problem in a way so that the "wrong" person's approach would have issues.
The thing I don't like about dueling patterns, as fun an opportunity to show off as it is, is it perpetuates the myth that there's a "right" answer. It's particularly bad when you pit two different languages against each other, because the APIs and patterns and idioms that work well in one might not be so elegant in the other. For example, writing my post with an early version of C# that lacked delegates would mean losing a lot of my cooler tricks.
So I got sucked in. I was bored, and having a beer with a lot of time to kill.
I feel like this is where we sit in the discussion:
"Here's my solution in VB6, it uses patterns A and B and I plan to extend it this way."
"I kind of like solving it this way in VB .NET, I can use patterns C and D to do the same thing."
"Ugh, no, you don't NEED OO code for this, I did it just fine with A and B."
"Whatever, patterns C and D are well-known and get the job done. Patterns A and B are known to have these problems, it's in plenty of texts."
"No, patterns A and B are perfect, it's C and D that have the problems. Please explain how you'd solve <intentionally bad C&D scenario> with C and D."
This is kind of the point where person 2 ought to roll their eyes and move on. VB6 has some weak spots and there will be problems it just can't solve in an elegant manner. VB .NET also has weak spots, and there will be tasks it fails at that VB6 can tackle elegantly. There's no really good general-purpose language that exceeds at all tasks, the best we can get is one that's great at some things and good at most. It is very possible that both people are right, are using perfectly fine approaches to the problem in their language, and would be up the unsanitary tributary if they tried that approach in the other person's language.
We mustn't get insulted when someone thinks another approach is better. If they're technically wrong, you can comment on that, but it doesn't need to be a "won" argument. Later, someone reading the thread can see a proposal->rebuttal->counterargument discussion and decide for themselves what is best for their solution. Heck, for almost every problem we've discussed I can come up with a scenario where the "good" advice is totally wrong. We need to know all solutions, with all their upsides and downsides, to make the best decisions based on our information, schedule, and budget.
Yeah, that's why I tried to stay out of it for... I think my last reply prior to this was somewhere north of page 10... it turned into dueling posts... as much fun as the Duck Pattern debate was, it degraded pretty fast... and no one seemed to want to back down. Olaf has his way of doing things that works for him great, more power to him. It doesn't work for me. But that doesn't mean he's wrong, nor does it mean I'm wrong. I'm not sure I'd follow DDay's pattern either (I think I attributed that right, I can't go back to the other page at the moment to look it up - if I get is wrong... mea culpa) doesn't make him any more wrong than Olaf either... I'll be the first to admit - I'm a bit jaded when it comes to VB6... I spent far too many years battling it, and yes, it was likely due to bad design on the system on our part... I won't fully throw VB6 under the bus, maybe just under the front wheels. And maybe if we had been willing to redesign our Duck, I'd have a more positive memory of VB6... but it left a bad taste in my mouth towards the end. I moved on to .NET (by choice) and never looked back. I'm happy where I am. I can understand some people willing/wanting to hang onto VB6 for as long as they can. It's a fine language, and there is a lot it can do. But to be honest, between the framework and the IDE, I'm far more productive in .NET than I ever was in VB6. Lambdas and LINQ alone are the two greatest things I use everyday that I don't want to think about having to solve in VB6. I'm not saying it would be impossible, it just would require a few more hoops for me to jump through.
That said, while I think it's perfectly fine for people to want to try to hold on to VB6 for as long as they can, I think they are doing themselves (and possibly others) a huge disservice by not expanding their skill set. It doesn't have to include .NET or JS... but they should be more than a one trick pony. That's where the real value comes in with any language. Olaf seems pretty knowledgeable on the inner workings of VB and the APIs and such .. and I suspect he has more in his toolbox than just VB6, and that's going to work out just fine for him... But I sometimes worry that his pro-VB6 advocacy, while respectable, is going to lead others to think that all they need to know is his vbRichClient and that it's going to work forever... but unless others have the same or similar understanding of the inner workings, it's going to fall apart when he gets hit by the proverbial beer truck (sorry Olaf).
Dang... I was going somewhere with this now I've lost it. It seemed like a good point though.
This is a beautiful quote - I've lived the ASP.NET ViewState nightmare
There are so many great solutions out there. To assume that Microsoft has ordained The One True Way is absurd. If that was the case, we'd all still be using visual designers in Visual Studio to drag and drop button and link elements onto a WebForm surface and we'd wire up the button and rely on ASP.NET ViewState to help insulate us from the "horrors" of scary HTTP. The day I got rid of the last WebForm from one of my deployed code bases was a day of glorious celebration. Literally.
(And who ever thought "web controls" was a good idea? Apparently I did because I drank the Kool-Aid and embraced it to the fullest. It bit me hard. Ever seen a 2MB+ ViewState?)
The first statement though - there are so many great solutions out there.
Getting into a browser based GUI gave me tons of cool tools all with big communities that embrace them (my graphs are animated and I didn't write a line of that code - props to jqPlot).
Last edited by szlamany; Aug 18th, 2015 at 10:00 AM.
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
I skimmed his "The Good" and mostly agree, though I don't have a lot of experience with all of the technologies. Obviously the real thing people want to argue about is "The Bad".
I think the thing that is most frustrating is the closed-mindedness he mentions, and it mostly causes every problem in his "bad parts". IMO, it's not .NET I want to leave, it's Windows. But I don't really believe that *nix is green pastures on the other side, it's just different brands of evangelism and religious devotion to particular toolchains.
But at least there's multiple *nix religions. The Church of Windows has no room for products that aren't blessed by the VS installer. Which is a pity, because TFS and MSTest are abominations, as are many software engineering tools once they're squeezed through the least-common-denominator filters of Microsoft's developers.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
Apologies. I was actually talking about the GZdoom source which is a C++ port of the original code. It introduced a lot of modern features to the old engine including the ability to play on modern OSes. I have the source for this port.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
An obscure body in the SK system. The inhabitants call it Earth
Posts
7,957
Re: What if there was a NEW vb6
This is kind of the point where person 2 ought to roll their eyes and move on
He's getting close.
Olaf, the simple reason I haven't accepted your challenge to add new actions or persist data is that the strategy pattern is nothing to do with either of those things. Those are not the problems it's designed to solve. You might as well visit a car showroom and then, when shown Ford Pickup say "Ah but how many wash cycles will it take to get my whites whiter?"
The problem the strategy pattern is designed to resolve is that it allows any combination of behaviours to be applied to new Duck class without restriction from an inheritance tree.
I do think I was quite clear, way back in post 753, that I was demonstrating the strategy pattern. I was clear (and overly verbose, I suspect) in explaining exactly what problem the strategy pattern is designed to resolve. I was also clear when I said that VB6 cannot be used to implement the strategy pattern (and it can't). Finally, I think I was clear when I said "I'm sure you can find a way to work around that but I'm willing to bet you won't be able to without either violating the DRY principle or increasing the coupling between the classes. I'm willing to bet I'll see a pretty chunky Case or If statement appearing somewhere." Note that I did not say VB6 could not solve the problem, I said it could not implement the pattern.
Your current implementation does solve the problem but it does so in a way that both increases coupling and relies on a big switch. It also violates the Open Closed principle. You may not see the problem in that but some of us do and a quick google for "Low Coupling" and "Favour Polymorphism over Conditionals" and "Open Closed Principle" will quickly demonstrate that we're not alone. We're not making this up. It will also tell you why those things are considered good design principles far more eloquently than I can managed.
I won't comment any further on your implementation, though, as I don't think it's doing either of us any favours. I am going however going to carry on addressing some of the challenges you and others have raised.
In the interests of taking the example a bit further and implementing at least some of the features that have been discussed in this thread I thought I'd consider adding a new type of action to the structure (Post 758 - "introduce the new Property 'NursesYoung'"). I haven't gone with NursesYoung because the thread has moved on and introduced the concept of dancing ducks and that is much funnier.
I think the best way to handle that depends on why you're adding a new action. If you're a consumer of someone else's library but you want to extend it's behaviour I would recommend the Decorator Pattern which will let you extend the properties of just about any closed box. I think, though, that the scenario Olaf was considering was more akin to being the owner of the core product and wanting to extend it's functionality before shipping it to my customer base. In that scenario it's all about being able to ship reliable code.
To that end the primary concern, in my opinion, is not how many lines of code are required, but rather how easy it is for me to make a mistake and not notice. Ideally, if I make a mistake, I want to know about it at compile time. I don't want to accidentally forget to include one of the ducks in a switch statement (which is the human error that could be made in Olaf's implementation) or forget to set a behaviour in one of the concrete duck classes (which is basically the same human error that could be made with my previous example) and have that somehow get out the door. I want my design to police my code.
First of all, we want to set the default behaviours in the base abstract class. That way I can go to one place and add a new action. The constructor now looks like this:-
Code:
public Duck()
{
SetDefaultFlyBehaviour();
SetDefaultQuackBehaviour();
}
and we add a abstract method to make sure our derived classes do what they're supposed to and set their behaviours
All my derived classes immediately break. None of them has implemented those abstract methods so they no longer fulfil the contract laid out by the abstract class. They won't compile so there is precisely zero chance of shipping code at this point. The police are watching and I'm glad to have them there. Even better, the error list is presenting me with a nice to do list which will take me to each amendment I need to make merely by double clicking.
So now I need to start updating those derived classes. This isn't difficult, I simply move setting the default behaviour for each action out of the constructor and into an apropriate setter method. A mallard, for example, now looks like this:-
Code:
public class Mallard : Duck
{
protected override void SetDefaultFlyBehaviour()
{
flyBehaviour = new FlapWingsBehaviour();
}
protected override void SetDefaultQuackBehaviour()
{
quackBehaviour = new QuackBehaviour();
}
public override void Display()
{
System.Diagnostics.Debug.WriteLine("I'm a Mallard");
}
}
So now everything's working again and I know now that I'm being properly policed. Note that the work done so far is not to do with adding the action, it was to do with putting the police force in place. You'll only do it once and we can now proceed to add a new action with much more confidence.
We need a member variable for the dance behaviour (I'm actually going to make this a property to support Inversion of Control, more on that later):-
Code:
public iDanceBehaviour danceBehaviour { get; set; }
We put our policeman in place to make sure any derived classes behave themselves:-
public Duck()
{
SetDefaultFlyBehaviour();
SetDefaultQuackBehaviour();
SetDefaultDanceBehaviour();
}
And we add the action method:-
Code:
public void Dance()
{
danceBehaviour.Dance();
}
The error list is once again telling me that my derived classes are miss-behaving because they're not implementing the new behaviour setter so I can trivially visit each in turn to set it's default behaviour. And the best thing is, there is zero chance that I will accidentally forget one. More than that, when I ship this to my customers, the policemen I put in place will be watching over their shoulder too. If they've derived their own ducks then this is going to shout at them, in no uncertain terms that they need to specify the default behaviour for all their ducks.
NB. to anyone whose paying attention, yes this breaks backward compatibility but it does so deliberately. The assumption here is that whatever changes I'm making to my consumer rely on the new action being in place and I want to shout from the roof tops if it isn't.
NB. Also at this point I moved Swim from Inheritance to Composition. Inheritance does provide simplicity but the hunger in this thread seems to be for flexibility and far be it from me to disappoint.
The effort to add the new action really wasn't great. 3 lines of code and a trivial single line method added to the base and then allow the error list walk me through the changes I had to make to any concrete classes.
But having the confidence to ship isn't just about how I write my code. It's also about how I test it. I want to be using TDD for this stuff (and really should have been doing so already) and to do that I want to be able to test any possible combination of behaviours. I don't want to have to actually define a duck for every possible combination (a flying lead duck that floats seems unlikely to be needed... and potentially hazardous) but I want to be able to test that such a beast is possible just in case it's ever needed and for that I want Inversion of Control.
Inversion of Control is the principal that you don't ask an object what is, you tell it what you want it to be. In other words, although I might set default behaviours for my ducks, I want to be able to tell a Rubber Duck to damn well sink if I want it to.
There are two basic ways of achieving this, you can implement a constructor that receives the desired behaviours as parameters and overrides the defaults or you can offer public setter methods. The primary difference between the two is that the former method makes immutable objects while the latter makes mutable ones. There a load of raging debate about which is better and the trend seems to be toward immutable at the moment but I'm a bit old school and prefer mutability so I'm going with the second option. The implementation is simple and you've already seen it, simply change the behaviour member variables in the base class to be public properties:-
Code:
public iFlyBehaviour flyBehaviour { get; set; }
public iQuackBehaviour quackBehaviour { get; set; }
public iDanceBehaviour danceBehaviour { get; set; }
public iSwimBehaviour swimBehaviour { get; set; }
I can now create any combination of duck I want. My Sinking, Squeaking, Flying, Lead Weighted fan of the Polka can become a reality. And if the consumer of my duck simulator wants a rubber duck to learn to paddle at run time it can.
Of course, I put all this in place because I wanted to enable testing and I really want to be able to text my duck behaviours independently of the breed or manufacture. It just doesn't seem instinctive to test a squeaking mallard so I'll create a mock duck that has no defaults:-
I've chucked this in the main project for now, just for convenience, but realistically this would probably go in a separate project. I can do that because I obeyed the Open Closed Principal
Another challenge that has been made is the ability to add new ducks and new behaviours. Well that easy because they're completely decoupled from the core of the design. Want to add a new duck? Just derive a new duck class. Want to add a new behaviour? Just implement a new derivative of the appropriate behaviour interface. This really couldn't be easier.
I wasn't paying attention when I implemented one of the duck classes. See if you can see what I got wrong.
@Sitten I haven't implemented flyable, quackable etc interfaces here because I'm describing a world where all ducks share the same actions, if not behaviours. It's a perfect complement to the Strategy pattern, though, and one I've used often. The strategy pattern allows you to have dynamic behaviours for the actions while the interfaces police that nothing asks something to carry out an action it doesn't understand
@Olaf I haven't implemented persistence because it was so far off the radar from what I originally intended to demonstrate and writing this up took plenty enough time already. I may or may not get around to it in the next few days. I'm supposed to be giving the house a coat of paint ready for some viewings by potential renters and I really should be focussing on that.
I'm curious as to why you think it's difficult though. It's just be a matter of taking Display out of the derived classes and changing it to a method in the base Duck class which accesses a resource based on the derived type. If you think your design offers something that mine doesn't in this area then go ahead and explain what. I'll try and match it.
The one last think I'd challenge you on is something you asked me to in post 791:-
"Please give an example for such an extension as a clearly formulated change-request.
After that let the both of us implement that request and compare notes - it really is that simple."
Here's the scenario: I do not have access to your source code, only your compiled library. Please allow me to implement a new type of duck.
Last edited by FunkyDexter; Aug 18th, 2015 at 03:00 PM.
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
This is something I can work with way better than the earlier sarcasm.
Don’t’ want to disturb your “duck hunting” experiance . Its getting more and more interesting since some of you are ready to name as “animals” even the duck-looking-stones.
If you have any reasons that make you believe that you could it better , (with sarcasm) please , just please , be my guest.Even I have to wait the “duck season” to be finished.
But before than that , let me inform you about something.
I totally respect those 300-400 persons I see every time I loggin , searching something about v*.net.
I also have no respect for any p***** ( 20-30 , no more) that says to me what I sould have done.
As a dino or caveman or what ever.
I just laugh at them.
I've stumbled upon this link, and I haven't find anyone that posted it on this forum, so here it is. I would like to hear your opinions.
Mikisoft i am almost certain you have posted a link to that exact same article before as i have read it before and i believe commented on it then but i will do so briefly again.
The article is piss poor in my opinion as the article title bears no relation to all the things he wants to leave behind!!
What it should be titled is "Why i am leaving Windows" as much of his arguments are to do with this then .NET itself, and even then i would say his article is poor as he even admits in most cases there are choices but because what he sees as the default choice is not to his liking then its BAD !!!
Also a bunch of his other arguments are to do with things that have absolutely nothing to do with the language, for instance choice of database or Source control. These things are a Choice, you have numerous choices also Source Control like GIT is available on windows and he has the choice of any number of databases he could use.
Its a bit like saying your leaving VB6 because Access is crap.
Some of his other arguments are equally as bad he say one of his other problems is "C# strongly encourages the use of locks and mutexes" and then goes on to say - "Even if I don't have any concurrency in my code, the default and preferred method is using locks."
So he is basically saying you can doing something badly using .Net and although i don't use it the fact that you can is a bad bad thing!!!
Pretty much all his arguments are like that they are terrible terrible arguments and it made me annoyed just reading it.
Now can we please move back to the Ducks, that discussion has been much more informative and entertaining !!!
Please Mark your Thread "Resolved", if the query is solved & Rate those who have helped you
NeedSomeAnswers, yeah that article looks for me familiar too, but I can't find that I or someone posted it here. Tried again to search now and it returned me nothing.
BTW. One more article: https://adtmag.com/blogs/dev-watch/2...successor.aspx
Looks like there is already a successor to VB6.
"There is a very large community of developers that grew up on VB6 and are still looking for a worthy substitute," said Erel Uziel, CEO of Anywhere Software. "Their voice is loud and clear - they want a modern RAD tool that will let them build real-world desktop and server apps without the hassles and complexity of existing programming languages. B4J provides an easy-to-use environment that lets developers get the job done."
Originally Posted by sten2005
Microsoft have repeatedly missed opportunities to update the VB6 programming language. They can hardly be surprised when others step in.
Anywhere Software are to be congratulated in recognizing this market opportunity and offering a successor to Visual Basic 6.
It is ironic that Microsoft developed their dotNet Java clone to compete with Java, but now find Microsoft's most successful ever language, VB6, is being replaced by a Java version.
An obscure body in the SK system. The inhabitants call it Earth
Posts
7,957
Re: What if there was a NEW vb6
Looks like there is already a successor to VB6
From what I've seen there's a few potentrial successors around. The feature that often seems to be missing is the ability to load up/port existing VB6 projects and that's feature that most of the VB6 users seem to really want. I couldn't tell from that article whether B4J supported that or not.
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
From what I've seen there's a few potentrial successors around. The feature that often seems to be missing is the ability to load up/port existing VB6 projects and that's feature that most of the VB6 users seem to really want. I couldn't tell from that article whether B4J supported that or not.
Unfortunately it's like others - it can't load or port existing VB6 projects because the platforms differ from each other. But it has a good syntax and a simple IDE, so if you know VB6 you don't even have to bother to look up tutorials about that.
I'm a little surprised someone hasn't built a conversion... the project should be easy, most basic forms too... the complexity comes when you've used a thrid-party control of some kind.
An obscure body in the SK system. The inhabitants call it Earth
Posts
7,957
Re: What if there was a NEW vb6
it can't load or port existing VB6 projects
That's a shame. It's the one killer feature that all these offerings seem to lack.
I'm a little surprised someone hasn't built a conversion
I'm guessing it's more difficult than it sounds. I know Olaf was talking about it in one of AxisDJs threads and he seemed to have ideas that would cover most of it but he was kicking it into the long grass while he worked on other things.
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
That's Java, how could it be a VB6 replacement?
To be a VB6 replacement (or "a new VB6", as the thread tile suggests) would have to be VB6 + some of the things that it lacks, imho.
That's Java, how could it be a VB6 replacement?
To be a VB6 replacement (or "a new VB6", as the thread tile suggests) would have to be VB6 + some of the things that it lacks, imho.
But unfortunately as we know, there will never be a language and architecture like VB6. Regarding that, B4X is a good option and IMHO it's more similar to VB6 than VB.NET will ever be, since it is built by a VB6 enthusiast who knows what's good and noticeably had the same problems like us.
Last edited by MikiSoft; Aug 19th, 2015 at 01:44 PM.
Here's a rough outline of a post I spent way too much time today on and couldn't finish. Weird food for thought.
VB6 was successful because Windows was the dominant business OS and it simplified client development enough to create a wider field of developers than WinAPI alone created. It also introduced RAD tools, and between those and the wider RAD methodology every language felt its impact. It changed expectations about how quickly software could be prototyped and delivered.
VB has always been a Trojan Horse designed to keep developers tied to the Windows platform.
VB6 and its runtime was coupled to the Windows API. This was especially true of the UI tools, which are really facades over GDI.
VB .NET isn't much better. While we have a working CLR on all platforms, WinForms itself is so GDI-centric it's easier to make a new framework like Gtk# than port it. Incidentally, those frameworks run on Windows.
No relevant number of people cared about this coupling because there was no relevant competition or demand for clients on platforms other than Windows.
Windows as a platform is endangered.
HTML is far more capable as a platform, and most people feel its shortcomings are mitigated by the fact that every relevant OS *must* have a browser capable of supporting HTML's features.
MS noticed this, it shows in their abandonment of WinForms for a plethora of XAML infrastructures: XAML has almost no Windows-centric assumptions, though WPF is still so Windows-centric it's unimplemented anywhere else.
But the many versions of the CLR behind each XAML-based framework all had tiny incompatibilities. It was very clear that the Windows API did NOT port well to non-Intel, non-PC devices.
Win10 looks like it might be unified across all devices, but if no one's buying Win10 PCs, tablets, or phones, who cares?
MS seems to be betting against a long-term Windows dominance.
Office runs on the web, iOS, Android, Mac OS, Linux...
VS Code is an IDE that supports non-MS languages on Mac OS and Linux.
VS cloud services performs many Windows-centric tasks off-board, meaning you don't need a Windows PC to compile, test, etc.
One of VS 2015's new features is the ability to compile Objective C projects, formerly a task only implemented by XCode. There's no Obj-C libraries or tools that target Windows. Hmm.
So IMO, if we want something to make a splash like VB6 did, it's almost silly to say it would focus on Windows Clients. It needs a UI framework that can target all or most of the relevant platforms: iOS, Android, and Windows at minimum. That UI framework needs some mechanism that connects it to the code, which must run on all of the same platforms. I'm very, very skeptical that this answer will come from Microsoft while they're still interested in creating Windows Client developers. And I think anyone who wants to bet their future on Windows Clients has very low aspirations.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
One thing sorely missing among most of the multiplatform development stacks though is a RAD-supporting IDE for GUI applications, from stand-alone to database client to general client-server client. That's VB's strength (and probably VB.Net's, C#'s, etc. as well). I doubt we'll see much like it again, since it isn't just about the IDE anyway.
The .Net crowd attributes far too much of this to Visual Studio. I think more of the credit goes to UI infrastructure that in VB is integral and extensible, in .Net less integral but still executed well, and in 3rd party stacks (and egad even more so in open source stacks) is almost always an afterthought. Yes, there are exceptions but they're rare and not what would be considered mainstream (REALBasic, Delphi, etc. are deader than VB6 for all practical purposes).
B4J suffers from this syndrome, stuck with the possibly-to-be-orphaned JavaFX which in any case often requires markup-level fiddling and tuning.
When I first started down the VB6 path one of my coders was very much into creating a .FRM for each client-facing maintenance screen. That one or two weeks of coding wasn't acceptable to me - maybe you guys code incredibly fast in VB6 but my coders didn't seem to be headed that way.
So I did what I've done for decades earlier on prior platforms - abstracted myself away from the UI form. Simple table in your database telling the UI form what to put up - a text box here - a label here - some radio buttons here. Now I've got database binding made easier - and a single event can handle ANY textbox losing focus. Actually since you had to have a floating textbox for FLEXGRID editing I made all my textboxes really labels and floated that same textbox onto the form for editing.
Now a customer facing maintenance form can be created in hours. That is RAD to me. And that form can change and the user see that change without leaving the app. That's maintenance-made-simple-gone-wild.
I've created that same environment in JavaScript with jQuery - DOM-created on the fly by loading up tables in the database with screen metadata.
That's RAD to me - but I'm just a boring database programmer.
Maybe a form for theatre lighting controls is way different (as one of the VB6 people here was bound to VB6 by).
Where do you all get your RAD experience with VB6? What kind of FORMS are you creating??
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
szlamany, I guess I just kind of wonder what the heck your developers were doing that took months to make one form, unless you're confusing the whole of development effort with form development?
I've heard of such "UI in the database" frameworks before, but I'm skeptical. You have to develop more or less your own markup language, and an application that can interpret it. If you're using HTML I guess that helps, but how do you version HTML within a database column? What's the automated testing plan?
I guess I'm just confused. What's a 'user-facing maintenance screen'? What were its functions, that took people weeks to finish? Given a random database schema and an IDE I'd expect to have a functional CRUD app in 30 minutes if I'm really grinding away, what's the complexity I'm missing? (I always worry this kind of question sounds snarky, I'm not being sarcastic!)
dilettante:
I never really associated it with VS as much as I did GDI. GDI was developed because GUI is what sold Windows, but deep integration between languages and UI isn't the sole domain of the "Visual Whatever" line. Obj-C and Cocoa were made for each other, Java's got 2 terrible UI frameworks, and GTK#'s what you get by with when doing C# on Mono. Most of these don't port well, because they are strongly coupled to an OS's system calls as opposed to being abstractions of a generally useful graphics API. XAML is a step in the right direction but again far too hitched to the Microsoft APIs to make for a reasonable port.
HTML's pretty much the only platform-agnostic UI framework we have. It makes me sad.
Last edited by Sitten Spynne; Aug 20th, 2015 at 03:21 PM.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
I said one or two weeks per form (not months) - I felt that was excessive. Maybe an attendance entry form for teachers or a form for loading invoices against PO's. More then just CRUD.
At any rate - it wasn't my intent to elaborate on my methods - I wanted to hear what people were making in VB6 and how the RAD-ness of it was so important.
I can appreciate that when I want to write a down and dirty little textimport program it's VB6 that makes that in 3 lines or less - imo. I've only created one large VB.Net heavy-UI app and it was sluggish - and the RAD-ness of the development seems to go down as the IDE gets more complicated - and yup that .Net IDE is a beast.
Although I do have one 5-project solution that mixes VB.Net and C++ and the .Net IDE allows effortless multi-project debugging. I would have been scared of doing something like that in the VB6 IDE.
Last edited by szlamany; Aug 20th, 2015 at 03:38 PM.
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
HTML's pretty much the only platform-agnostic UI framework we have. It makes me sad.
Qt is a solid framework, and its "signals-and-slots" construct is a natural fit if you're accustomed to .NET's events and delegates. QtQuick (and QML, its Javascript-like declarative UI language) is solid, too.
The main "difficulty" with Qt, if you want to call it that, is that it's all very C++ oriented. There are other bindings, but none are as stable as the default C++ ones.
But if you're comfortable with C++, I personally don't think there's a better cross-platform UI framework.
I guess I'm a bad person to ask. I've kind of inverted my workflow so I design UIs either last, or alongside code features. I'm starting to think the design-first nature of VB is harmful to people who want to take on medium-scale to large-scale projects. There's a stereotype of VB projects where they're just 40,000 line Form1.vb files, and skimming over a bunch of newbie projects doesn't do anything to combat it. I get the feeling a lot of people spend their career without the revelation that an event handler can call a helper method. And I wish I was being sarcastic when I said the majority of .NET developers seem to think creating a new class is a task ONLY for Martin Fowler-level certified architects. More and more it feels like Windows really does make people stupid.
But in less designer-oriented languages, it seems like there's more of an emphasis on separation of concerns from the start. There's some bad outliers, like PHP, but then there's some good ones, like Rails. On one end you have a language that hopelessly couples your UI and logic, and on the other one that can't function if you couple them. PHP has a REALLY bad reputation. Rails, not so bad.
I think UI is like an iceberg: I spend 90% of my work on the backend code, and it feels like the UI's just a mask I glue on it. It's only tricky if I'm asking for something that's not in the toolkit, like a knob control or a complex graph. Even then, I'm not using a designer, I'm writing 2D drawing code. The past few years, I'm not sure if I've used a designer at all outside of really quick example projects.
I didn't make good HTML pages when I used designers back in the day, I just spent less time thinking about HTML. If I had to come back and style them and make them work in multiple environments, I bet overall I'd have an easier time starting from scratch than trying to work around designer-generated code. But then, when 99% of my HTML pages are just plain text with a smattering of images, I don't really care if my backend code isn't optimized for extensible styling via CSS, do I?
Maybe that's what I figured out. Designer-focused RAD is great for small projects with well-understood requirements and easy logic. But at some level of complexity, you're spending so much more time on the backend than the UI you don't really care if you have a designer. In fact, because on this project we have a person with the title "designer", the UI is mostly picked out for me, I just have to make sure I have a way to glue it to the code I write. That glue is mostly boring to write, once you know a few tricks.
Last edited by Sitten Spynne; Aug 20th, 2015 at 04:28 PM.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
Actually design-first doesn't work well in VB6 either, if you mean UI design.
Most of the power tools for building RAD forms in VB6 require that the database and the queries and stored procedures all be designed and implemented up front. Then the IDE can extract database metadata to quickly build forms from that.
The most primitive example is the Data Form Wizard add-in. More powerful examples are all of the RAD features in the DataEnvironment, Data View Window, etc. Sadly most self-taught plinkers have no idea how to even begin to use these, which explains why so many never could pass the old VB6 MCSD exams.
If you have never had the IDE make a database connection at design-time, you don't know VB. It offers a far more holistic approach to development than the creay old "dark world" approach of command-line script with a GUI tacked on as an afterthought.
It sounds like my first dang VB project to me, and while the word CRUD certainly applied to that project I'm pretty sure it wasn't in the way the tool designers intended. It's hard for me to really work that angle though, as it was my first-ever VB project and far outside the complexity of what you should throw at such a greenhorn.
dilettante, I totally believe it for a single-table database, or maybe a 2-3 table one with some relations. I can imagine it making some samey UIs which is a good thing, you only need to train users once. For a particular and very, very common kind of CRUD app that is precisely what the doctor ordered. But beyond that it gets weird to me. Maybe it's because my project is a GPS navigation tool, and there's no way I could ever be binding to something as simple as a handful of textboxes or a datagrid. I can be outside of the use case of those wizards without declaring them useless.
I had some bad dang experiences with wizards that tried to connect my UI to my code. It didn't do well at all if I didn't want that samey interface. If we're narrowing the discussion to that context, we don't need anything but VB6's tool suite, sure. But I'm considering the entire breadth of application development. I'm talking about applications like Google Maps, Skype, Twitter, Netflix, Facebook... things people get excited about using, rather than get paid to use. I want my "new VB6" to make kids want to get into programming early, and I can't think of any age that gets stoked for writing customer invoice systems.
I don't know, I keep getting hung up on your condescension. For a while it was cute, but it's far less effective than practical discussion. If I have to use code wizards to be a "real developer" then call me Pinocchio, I'm doing really cool things with my fake skills. I think a relevant language will have to think outside the enterprise CRUD app box if it's to compete today, but if it happens to serve that niche too I'd like it as well.
Last edited by Sitten Spynne; Aug 20th, 2015 at 05:55 PM.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
An obscure body in the SK system. The inhabitants call it Earth
Posts
7,957
Re: What if there was a NEW vb6
Steve, I've heard you mention your "DB defines the UI" aproach before and I do find it intriguing. I'm not sure it would be my preferred aproach (though I'm open to reconsidering that) but I can see how it could seriously enable RAD, particularly with simple CRUD apps. Holding the data in the DB along with meta data that defines a UI and how it should bind to that data sounds like an elegant solution which would enable rapid development and simple roll out.
I'm intrigued as to how you handle complex behaviour though. You know, the complex business logic that many of us would hive off to some class or other. Do you somehow hold that logic in the DB too?
I'm aware that by referring to "simple CRUD apps" it might sound like I'm demeaning them. I'm not. Simple CRUD apps probably represent 90% of the business app that get produced and they've certainly been the vast majority of the applicatiosn I've worked on in my career. Anything that facilitates their development can only be a good thing.
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
And I wish I was being sarcastic when I said the majority of .NET developers seem to think creating a new class is a task ONLY for Martin Fowler-level certified architects. More and more it feels like Windows really does make people stupid.
Now that's not the experience i have had, but then my experience is mainly working in software houses with a number of development teams. In that environment you cant hide behind bad code practices, you get found out. Code is reviewed and developers are expected to know how to develop properly.
Maybe you have just been unlucky.
I did work in a place earlier in my career in which the developers worked in there own little silos with zero knowledge sharing and they tend to be not very healthy places to work and places like that tend top store up maintenance issues in there software so the developers spend much of there time just fixing bugs in unstable systems than introducing new features.
Please Mark your Thread "Resolved", if the query is solved & Rate those who have helped you
An obscure body in the SK system. The inhabitants call it Earth
Posts
7,957
Re: What if there was a NEW vb6
Now that's not the experience i have had
It's not experience I've had since I moved to C# but it pretty much describes my experience back in my VB.Net days (and in my VB6 days before that).
I think it's cultural and the culture stems from the 90s. Languages like Java and C++ were "proper" languages and VB6 was a "Toy" language (nb. not my opinion, I'm just describing the prevailing opinion of the time) and, as such, big software houses used Java and C++ while VB tended to be used by smaller software houses or IT departments in larger companies.
When .Net came along C# tended to be adopted into the large software house and VB.Net tended to be adopted into the small ones. There's no good technical reason for that, just that cultures tend to be slow to change. If you're in a large software house you do tend to work in teams with other developers while in a small one it's likely that you're the sole developer on the products you support and Rodney in the next cubicle is probably working on something entirely different. You might share a coffee in the morning but you probably don't touch each others code much so you tend not to get into the sort of technical discussion that promote learning as often. You're also probably under much more pressure to "just get it working now".
Having worked in both VB.Net and C# I do see some evidence that C# developers tend to be more interested in good development practices and software engineering while VB.Net developers tend to be more focused on delivering a quick solution that will work for now. This is a sweeping generalisation, of course, and an unfair one in a great many cases. There are, of course, many large VB houses and small C# ones.
I also don't think that this distinction is based on ability. Take any half decent VB.Net developer and expose them to a large software house with collaberative teams and they'll be talking patterns pretty quickly. Take any C# developer and put them in a small company where they only work on their own code and where the customer repeatedly rings them direct to tell them to ammend a bunch of data directly in the production database and I'm willing to bet you'd see them fall back on quick and dirty hacks that let them ship quick before you know it.
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
I am not sure if it's an Intellectual Property but I have always been intrigued by the method being used by sz, I think he may have picked up some ideas from mendhak in their conversation before, I was hoping sz could share a very simple CRUD using one table to showcase how his technique works.
Regards,
™
As a gesture of gratitude please consider rating helpful posts. c",)
This is a simple READ SPROC that returns all the USERS of the system
Code:
Create Procedure awc_StaffUsers @Staff varchar(100), @UserId varchar(100), @username varchar(100)
As
Set NoCount On
If IsNull(@UserId,'')=''
Begin
Select '["edit","reader","print"]' "boottab"
,'[]' "operators"
,'UserId' "editkey"
,'{"tabfulldesc": true}' "awcoptions"
,'Manage Users' "heading"
,'Users' "tabcaption"
Select AWCElement "acs-work"
,AWCOptions "options"
From AWCConfig_T
Where AWCType=5 and AWCFlag1='awc_StaffUsers'
Order by AWCSeq
End
Select AW.UserId, AW.AKA, AW.Employee...
from AWCUser_T AW
.
.
.
Where IsNull(@UserId,'')='' or AW.UserId=@UserId
Order by 1
You can see what the first SELECT returns.
The second select feeds a SlickGrid with grid/column meta data - that looks like this (that meta data is required by a SlickGrid plug in that I use):
The third SELECT returns data for the GRID. Notice the WHERE clause. This SPROC is designed to be called for a single ROW also (when that ROW gets edited by a DETAIL PANEL that comes up in front of the GRID).
And that draws a screen in my web app like this (using a jQuery SlickGrid library that is so, so cool). In a labor union customer I have I can returns 100's of thousands of rows to feed the SlickGrid - VB6 FlexGrid's used to tank when I returned lots of rows.
Next post I will show you the detail panel that opens up when you click that OPEN FOLDER looking button...
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
Here is a READ SPROC for the DETAIL panel. Any SAVE operation that happens always re-executes this READ sproc to return the "saved data" from the DB.
Code:
Create Procedure awc_StaffUsers_Edit @Staff varchar(100), @UserId varchar(100)--, @username varchar(100)
As
Set NoCount On
Declare @FromSave int
Set @FromSave=0
If Left(@UserId,6)='~save~'
Begin
Set @FromSave=1
Set @UserId=Right(@UserId,Len(@UserId)-6)
End
If @FromSave=0
Select '["save","add","undo"]' "buttons"
,'{"fixedheight": 475, "fixedwidth": 993}'
"awcoptions"
Select Cast(AW.UserId as varchar(100)) "UserId"
,EM.AKA
.
.
.
,EM.EmpType
,EM.EmpHours
,Case When IsNull(UR1.RoleLevel,'')='A' Then 'Y' Else '' End "RoleAdm"
,Case When IsNull(UR2.RoleLevel,'')='A' Then 'Y' Else '' End "RoleMgr"
,Case When IsNull(UR3.RoleLevel,'')='A' Then 'Y' Else '' End "RoleUsr"
,Case When IsNull(UR4.RoleLevel,'')='A' Then 'Y' Else '' End "RoleSp1"
,Case When IsNull(UR5.RoleLevel,'')='A' Then 'Y' Else '' End "RoleSp2"
,Case When Exists(Select * From AWCUser_T AU Where AU.Username=EM.Employee and LoginType='standard') Then 'Y'
Else 'N' End "LoginEnabled"
,(Select Top 1 '"'+LA.ActivityType+'" '+LA.ActivityText + ' ' + Convert(varchar(23),LA.ActivityDate,121) From AWCUser_T AU
Left Join AWCLoginActivity_T LA on LA.UserId=AU.UserId
Where AU.Username=EM.Employee and LoginType='standard'
Order by LA.ActivitySeq Desc)
"LoginStatus"
Into #XYZ
from AWCUser_T AW
LefT Join Employee_T EM on EM.Employee=AW.UserName
Left Join User_T UT on UT.UserName=AW.UserName
Left Join UserRole_T UR1 on UR1.UserId=UT.UserId and UR1.RoleId=1--select * from role_t
Left Join UserRole_T UR2 on UR2.UserId=UT.UserId and UR2.RoleId=2--30001
Left Join UserRole_T UR3 on UR3.UserId=UT.UserId and UR3.RoleId=3--30010
Left Join UserRole_T UR4 on UR4.UserId=UT.UserId and UR4.RoleId=4--30101
Left Join UserRole_T UR5 on UR5.UserId=UT.UserId and UR5.RoleId=5--30102
Where AW.UserId=@UserId
Note that is also detects the lack of a record (as in we must be adding) and returns a nice default recordset to the web app
Code:
If @@RowCount=0 Insert into #XYZ values (@UserId,'','A'
,'','',''
,''
,'',''
,''
,''
,'','','Y','',''
,'Y','* New User being Added *')
Select * From #XYZ
Drop Table #XYZ
Go
And this is the screen that appears. Now this HTML I do have to feed to the web app - I'll show that in the next post...
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
This is what the HTML looks like for that detail panel. This HTML loads via an AJAX call - you can even execute the AJAX yourself so that when you are modifying these screens you don't have to re-login to the web app to get fresh HTML's for the detail panels.
Radio button data binds to a textbox with the CSS ACS-EDIT-HIDDEN-TEXT (above) - which of course hides the data - and also BINDS it all to the RADIO buttons.
Ok - here are two buttons that call SPROC in the database - and those AWC-CTRLVAL# items are passed to that SPROC call
The really cool thing about that SPROC button is first, obviously, it make an AJAX call. What comes back in JSON is a whole set of instructions that can hide buttons and update fields on the screen
I showed you simple - that was a simple screen with just a couple of buttons.
Below is where the cool stuff happens - in my meta data for the detail panel for instance - this one is for a task based tracking system. I can add new features through this metadata and make the JavaScript do whatever I want whenever - not tied to what ASP.Net decided I can do...
Code:
If @FromSave=0
Select '["save"'+Case When @FromEmpty=0 Then ',"add"' Else '' End+',"undo"]' "buttons"
,'{"fixedheight": 475, "fixedwidth": 993'
+', "reseteditkey": "TaskId", "view": '+@View
+Case When @FromEmpty=1 Then ', "adddirty": true' Else '' End
+Case When @FromAdd=1 Then ', "saveoptions": true, "nomsg": true, "resetview": true'
+', "noclearsave": true' Else '' End+'}'
"awcoptions"
Notice the VIEW element in that JSON - and tons of other little aspects of how I want the UI to behave.
This task system is very complicated UI. Notice all the acs-edit-view-x CSS tags - that controls what panels appear based on what type of TASK you are creating.
This is the VIEW that appears when you click the ADD button to start a new task - basically VIEW 0. Notice the HTML for VIEW 0 above only has two elements - a textbox with class acs-class-datepicker (which makes that nice jQuery date picker appear in the html). And that other element just called awc-addtype (and that class it has called acs-divmulti). The SPROC actually returns HTML in that field which gets loaded onto screen. The acs-divmulti tags is used in the JavaScript to help fill that field and also read from it when SAVE's are done.
I just added this logic last month - first time I had a set of RADIO buttons that had to come from the type of user. I could have done it with a bunch of hidden HTML but I wanted to make the field really be based on what TYPE's of tasks might be in the TASK TYPE table.
Last edited by szlamany; Aug 21st, 2015 at 06:36 AM.
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
I am not sure if it's an Intellectual Property but I have always been intrigued by the method being used by sz, I think he may have picked up some ideas from mendhak in their conversation before, I was hoping sz could share a very simple CRUD using one table to showcase how his technique works.
Mendhak totally predicted my VB6 days were numbered and I was headed into the web world - I thought him nuts at the time.
The past 3 years of this JS app has been a breeze! I'm not saying my VB6 decade was hard - just a jeep compared to my new SUV...
Last edited by szlamany; Aug 21st, 2015 at 06:47 AM.
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
Steve, I've heard you mention your "DB defines the UI" aproach before and I do find it intriguing. I'm not sure it would be my preferred aproach (though I'm open to reconsidering that) but I can see how it could seriously enable RAD, particularly with simple CRUD apps. Holding the data in the DB along with meta data that defines a UI and how it should bind to that data sounds like an elegant solution which would enable rapid development and simple roll out.
I'm intrigued as to how you handle complex behaviour though. You know, the complex business logic that many of us would hive off to some class or other. Do you somehow hold that logic in the DB too?
I'm aware that by referring to "simple CRUD apps" it might sound like I'm demeaning them. I'm not. Simple CRUD apps probably represent 90% of the business app that get produced and they've certainly been the vast majority of the applicatiosn I've worked on in my career. Anything that facilitates their development can only be a good thing.
I'm a bit of a radical when it comes to business logic.
I believe it belongs in SPROCS in the database.
I do things like CALCULATE a payroll in SPROC - not small stuff - 1000+ employee towns.
The nice thing about calling a CALCULATE payroll in a SPROC is that you can do it with ROLLBACK.
And to add more sugar to that you can do it in EVERY single report SPROC.
Why is that so powerful?
Now you can run a deduction register, for example, and have it be run in PRE-CHECK mode - before the actual payroll for a week is committed.
Sure you could do that in code - hold a transaction open. That is not something I consider a viable option with SQL.
I do big things in SPROCS. Schedule high school students into classes - a SPROC call that can take 30 minutes.
Adjudicate medical claim payments - all in a SPROC.
So I am 100% business logic in SPROCS - which really works nicely with my web app concept of UI-in-DB.
I did the exact same thing in VB6 - UI-in-DB.
And that old VB6 app is still in use - here's a quick select off an Application Connection tracking table at one of my older clients.
Select Min(OpenServTime),Max(OpenServTime),Sum(1) From AppConnect_T Where AppTitle='AMC'
180,000 runs in 12 years - 53 a day (small number of users - maybe 50?)
I had a report writer engine buried in that VB6 app which I just ported to .Net and loaded up into my web methods - now I've got 100's of reports from the last decade that now can get generated as PDF's in my web app - automatic preview that the browser gives me - very nice.
I am very busy so DRY is more then an development principle - it's a life style with me.
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
The platform sz has is similar to what we've built here... although, I think ours a little simpler, and we use XML files. The cool thing about it is that all you need is the basic platform, a SQL Server & database, and you can develop just about any kind of app. We've used the platform to build our main system that we sell to the clients, but we've also eaten our own dog food by using it in house for a configuration management tool, an on-line service tool, I think we should expand it to also run our in-house IT help desk but that's out of my sphere of influence, we use it to run our online documentation and self-help forums... it's pretty powerful and ingenious... and infuriating all at the same time.
Everything is built as componments using "spec" (specification) files, which are then loaded into the system... these components can then be used stand alone, or even as a block in another spec...
Example - using sz's example above - let's say I want to display a list of students, be able to add new students, and edit existing ones. What we would end up with are 4 spec files: The list, an add form, an edit form and the page that puts all of the components together.Correction - 5 spec files... I forgot I'll need a students table as well -- which yes, we also define through a spec file... when it is loaded, the loader will issue the CREATE TABLE (or alter table if I've changed the spec) automatically for me.
Keeping out the IP stuff... here's what I'd end up with:
Code:
<TableSpec
Id="{guid value}"
Name="STUDENTS"
Description="Table containing a list of students enrolled."
Developer="TG"
>
<Fields>
<Field Name="STUDENTID" Description="Friendly ID of the student" DataType="String" MaxLength="9" Required="true" />
<Field Name="FNAME" Description="Student's first name" DataType="String" MaxLength="50" />
<Field Name="LNAME" Description="Student's last name" DataType="String" MaxLength="100" Required = "true" />
... more fields as needed...
</Fields>
</TableSpec>
I didn't include "ID" as a field as it is automatically added for me - in fact the schema will throw a fit if I do try to include it. There's also a number of other featres I didn't include such as indexing, fkeys, even linking this table as an extension of another table such that the IDs will match one-for-one if need be (this allows us to extend base tables with out actualy altering thsoe table in the chance that the platform or product people chenge them... it allows us to isolate our customizations/changes w/o fear of them being overwritten.)
Once load that, I have a table, ready to go, fully audited and everything.
Now I need to add a student to the system.
Code:
<AddFormSpec
Id="{guid value}"
Name="Student add form"
Description="Adds student records to the system."
Developer="TG"
>
<SPDataForm>
<SaveImplementation SProc="USP_STUDENT_SAVE">
<CreateProcedure>
<![CDATA[
create procedure dbo.USP_STUDENT_SAVE
(
@ID uniqueidentifier = null output,
@STUDENTID nvarchar(9),
@FNAME nvarchar(50) = null,
@LNAME nvarchar(100),
@USERID uniqueidentifier = null
)
If @ID is null
set @ID = get_id()
-- there's more stuff to do here, like checking the USERID (the person creating the record) and setting it if it is null (connection is used for that)
-- then insert into the table:
insert into dbo.STUDENTS (ID, STUDENTID, FNAME, LNAME, {more fields here as needed...}, CREATEDBY, CHANGEDBY, DATEADDED, DATECHANGED)
values (@ID, @STUDENTID, @FNAME, @LNAME, {more fields as needed...}, @USERID, @USERID, @CURRENTDATE, @CURRENTDATE) -- Current Date variable is part of that "other stuff"
return 0; -- success
]]>
</CreateProcedure>
</SaveImplementation>
</SPDataForm>
</AddFormSpec>
That's where it starts... then we can define the next section which defines the UI Fields
Code:
<AddFormSpec
Id="{guid value}"
Name="Student add form"
Description="Adds student records to the system."
Developer="TG"
>
<SPDataForm>
<SaveImplementation SProc="USP_STUDENT_SAVE">
<CreateProcedure>
<![CDATA[
create procedure dbo.USP_STUDENT_SAVE
(
@ID uniqueidentifier = null output,
@STUDENTID nvarchar(9),
@FNAME nvarchar(50) = null,
@LNAME nvarchar(100),
@USERID uniqueidentifier = null
)
If @ID is null
set @ID = get_id()
-- there's more stuff to do here, like checking the USERID (the person creating the record) and setting it if it is null (connection is used for that)
-- then insert into the table:
insert into dbo.STUDENTS (ID, STUDENTID, FNAME, LNAME, {more fields here as needed...}, CREATEDBY, CHANGEDBY, DATEADDED, DATECHANGED)
values (@ID, @STUDENTID, @FNAME, @LNAME, {more fields as needed...}, @USERID, @USERID, @CURRENTDATE, @CURRENTDATE) -- Current Date variable is part of that "other stuff"
return 0; -- success
]]>
</CreateProcedure>
</SaveImplementation>
</SPDataForm>
<FormFields>
<FormField FieldID="FNAME" Caption="First name" DataType="string" MaxLength="50" />
<FormField FieldID="LNAME" Caption="Last name" DataType="string" MaxLength="100" Required="true" />
<FormField FieldID="STUDENTID" Caption="ID number" DataType="string" MaxLength="9" Required="true" />
</FormFields>
</AddFormSpec>
The platform then knows how to read that and transform it into an html document that can be fed to a client browser. It will automatically have save and cancel buttons. If I try to enter a student without an ID, it will let me know, same with the Last Name... it will also limit my entry to the appropriate number of characters.
The list of FormFields also needs to match the parameters of the sproc - with some exceptions, like the ID and UserID which are auto parameters - or it will not load - I'll get an error and it will tell me that FormField X is not specified... vice versa too... if I accidentally include a FormField that is not a parameter, it will warn me.