WWDC2001 Session 613
Transcript
Kind: captions Language: en my name is Alec no mayo I'm going to talk to you about John COF I'm I'm Matt we work in the field and the manager for the I services team in France that's in Europe that's you know on the other side yet nothing and it's I actually have a really hard session there because I'm just between director web and you like to Java client right so two technologies where you don't write code you write rules and so nice and I'm going to talk to you about how to build an application writing all the code you know I'm I'm a developer so I code that's what I do for a living so I'm going to talk you about the code where do you put it what do you put it what kind of code do you write and how do you build a web objects application I'm going to bring you from the beginning to the end building a web objects application start from somewhere you know other thing and you go to the end I'm going to try to do that in in a logical way in a way you can build an application it's not firm you can do your application some of the ways you can start from another point you can and you can also eat it right you can do a small part of your application this way and then come back to the beginning and we do another small part and cycle so it's just to give you some pointers whether where do you go to write a new F application so where do you start well most of the cases you start from your data the application you want to manipulate some data you want to you already maybe have some that time the database you want to access or you're writing a complete new application and and you want to create the complete database put your data in it and control everything so the first thing you have to think about is what is the data you're going to manipulate what is your data model some people are like doing you know nice graphics with plenty of boxes all over the place and nice lines between them some of the people just you know scrum but some stuff on a piece of paper and some of the people just stopped write code I'm mostly in the in the last thing but that's that's a bad thing you don't want to start like this you probably want to stop by understanding your that time and by understanding where you're going so what are the the pitch fool when you are doing your data Modell what's what are the problems we can have with you f when you when you just even before using you F when you out your data model you doing your data model what other thing the thing you need to think about first of all your design when you do a design and you put things in tables all over the place there is always performance application if you explode everything and you have tables everywhere well every time you're going to do a stretch you're going to do 60 joints and your database is going to be need to do all these joints all over the place it's hot in some of the ways for example here the blobs if you have big chunk of data and this big chunk of data are in the same tables and some of the data every time you're going to fetch a neo you're going to fetch this blob well if this blob is a nice image and 2 megabyte in size every time you want to show a list of euros on the screen you're going to fetch for every one of those two megabytes data that you actually don't really need so it's actually easier to take this blob and to move it in a separate table so you don't have to to load it all the time just load it when you need it same thing with inheritance inheritance is nice it's a nice way of thinking about you know to partition my model and I'm going to take this example that we talked about that I heard about before that but the person and the student and the student and and the professor it's nice you separate that nice in every turn story and you create one table for each and you do nice joints all over the place what if it's one layer deep probably okay two layer deep we start getting you know a little router if you go really deep well it's a huge performance impact and you're going to search our applications going to suffer for that so you probably want to correlate some of these classes together to to make some compromise in your design in order to get some more performances but you have to think about this when you build your data model trigger stored procedure we can deal with it with UF so we some way to code stored procedure there is some way to deal with triggers but those things are making you job others you're writing a database from scratch if you're writing your model from scratch don't put any of these in there except eventually for modification dates or creation dates you can use triggers for these things but otherwise try to avoid those if you have some in your in your model you can deal with them for triggers every time you save something and use there is some triggers you have to invalidate everything that's around and we fetch them from the database because the debates change behind your back stored procedures just a different kind of invocation in working something to get some data back so you have to write some code to do an invocation of a stored procedure and on the data model at left button at least you have to think about how your primary key are generated primary here the the core every time you create an object you're going to need a primary key for it and it's there is multiple ways to deal with primary keys with the UF so when you build another data model you have to see what are the choices you have and which one you're going to pick the first is easy where it just lets you adapt to undelete the JDBC gtb/c adapter knows how to do it the result the different plugins can do things differently but basically the adapter know how to create a primary key you might be primary key in your model as any kind of integer just going to work in web objects fives are actually performance improvements in this area because you're always getting this thing in batches and not just one by one so if you insert a thousand objects or is not to size on one trip to the database just uh I don't know me you primary key it's generating a unique number from your process ID the bottom number you're using and sort of the time and some of the data is building this huge of 24 by binary thing and and that's it and you save a primary key in the database sometimes not if you need to present a primary key to the user that's definitely not a good choice after all exactly similarity remember that if you have an existing some existing data and the primary key generation in there is specific and doing some weird thing taking actually current values that exists in the object and concat and put them together you can implement the delegate database context new primary key and I'll just return a dictionary from there that will be a priority of your object all the last the easy way is if you want to do something simple is you can mark the primary key an attribute of your object and fills a new set when the object is inserted in your editing context say oh there is no primary in there let's put something and get to something from wherever you want so you've built you use you've build you data model or you thought about it you know where all the data is going to be you're going to design the data and now you have to be modified you know this magic in in in joy to web and your actual Java client is all happening because there is a model file and just we there is wounds extracting stuff from there so you need a modifier and the modifier is actually not that easy to get right so my first tip on your model is spend time on your in your model just don't try to rush it and just write on your model and go write your application just you know look at look at the yo-yo model and click on all these inspectors if there is checkbox you don't understand in there well maybe you should understand it and maybe you should look in the documentation try to find what this thing is doing or writing a little test application trying to see what this thing is doing one is changing the other you can also compare your relationships duration you're building we ship some example your model in in web objects in the examples just compare the relationships you have with relationships in the model try to think how do they defeat the same way in your design you'll is it the same kind of relationship and look at the relationship and see see in the inspector if they look similar if something is different try to think why it's different and finally just take this model and use one of these great direct to something technology and just drop your model in there run the direct to Java client application if the application looks like something you can use your model is probably okay if your application look like is we are there with entities that you don't expect there but then you know it's in a separate window should be in the same window maybe you do not express the relationship exactly right the heuristics in direct to Java client but Carol yeah I really excel and giving you a good overview of your of your data model okay so I have a small application that actually build most of it on in the plane next web app or a book it's fitting that on the tray so a builder is a small project a small project and inside this thing it's yet another bug tracker system with a different database so different know do different everything not just everybody needs a book tracker system and everybody wants its own opening double-click on it okay so that's a good start for demo there we go I have two times now that's probably completely swept out okay so it's just a really simple model file okay doing to make it bigger you have a bug bug has some component is is part of a component there is some priority some state some comments on this burg from some users a user on the burger user on the command a user on your components this kind of this kind of relationship actually this one is not the simplest one I can can show there is something simpler so it's a really simple model but I just want to use this model to show you some some little little things as you know you know the data is usually little data bitzleberger exist you have one you have something like five different priority in your model in your in your data and you have maybe ten thousand words so something you probably don't want if you go look at priority yeah it's a Russian ship to Berg should probably not be a class properly should not probably not be part of your of your of your priority object because if it's part of a priority object every time you you add a new bug with this priority where we need to add it to add this bug into the array of all the bugs of this priority so you're going to fetch all these objects interests in order to install this thing into it into this array so and it's it's it's a costly fetch so this Russian ship the inverse relationship is very important especially from a black you want to know what the priority is just by following a pointer but the other way you probably don't want it so the first reason is performance you know you you have this thing then you have this huge array and you don't want to fetch it the second reason is the priority you probably want to fetch it at the beginning when you launch the application you want to fetch all the priorities other states and this this information that's you know standard for all the bugs and you can modify and you probably want to share this information by everybody by every single leading in context in your application every single user in your application is going to use the same objects and in order to do that you use a share leading context so share leading context is a place where you can put objects and every other editing context in the application can use these objects directly you only have one copy of these objects in memory what that mean is your object in your own editing context can have a pointer to this priority you know your bug has a pointer to this priority but then you are in your share late in context you have already shared object and imagine that you have a pointer to other bugs well all the bugs where all the bugs in shared in contact and editing context of this session or the editing context of this session you don't have the information so you cannot put you cannot make a new you cannot share an object that has a relationship to data that's not shared so you need you have one way point direction going from your your objects into shared object but from the shared object you cannot go out to and to an object that's not shared so that's that's why it's this thing is not a class property I see like to put the relationship in the model though because it's actually useful information that something you can actually use when you're programming that yo access level you can say I want a Russian ship named bugs and grab it from the model and do some stuff with it you know qualify qualifying or fetch something like this if you don't have a Russian ship well you have to drill it first and it's our it's nice to have it in the model file let's go back to the to the slide so what I'm going to say on this model is very simple so once you've built your model file you have to think about your logic where are you going to put to put your logic what kind of what kind of code do you do you write you know you have you have plenty of coats right in your application and some of them are more you know database code suppose I'm more UI code some of them up somewhere in the in the middle so I'm going to show to review the different class of code you have to write in your application and where do you put it and I'm going to start with something I called yo logic so it's basically everything that's on your enterprise objects the precede the first choice you make with entreprise objects probably knowing what is you entreprise object where did you serve class you have you have choices their first choice is you can use a new generic wicker a new generic record is just think think about it think about it's just a dictionary there's something you don't see some values and it's just somewhere where you put your data there is no code no logic it's just your data so you just don't quit code on this it's useful for some little objects where you don't want to put some logic on it for example my priority object probably I don't want to put code on it I can just make it an use in your record and forget about it you can subclass using your record if you want to add logic to it or you can use a custom enterprise object that actually the superclass of yo generic record to build more powerful full-fledged object the choices of suppressing using your record or custom enterprise object it's just a matter of taste actually in web objects 4 5 there was a huge performance improvement if you were so placing using a quick road for long reasons but in web objects 5 you don't really care I can suppress one of the other the only difference between the two is using your clicker by default isn't promoting a feature that's called deferred floating and custom enterprise object by default don't implement deferred folding customer entreprise objects are actually my favorite because I like to control everything you know I'm a freak and writing code but your generic record just work and actually the first thing you do when you create an entrepreneurship is you go into your module click the button and generate the classes tab for the classes and you were basically you write your accesses this is standard access or for some things i69 in your generic record you have something written in the title and something setting a title you see that I'm so classing using every color I have this weird code to all value for key take stored value for key I'll get into that in a minute because this is this is the way the framework is accessing your object and you have to understand how the framework says sex in your object to know we have to put your code because if you don't put your code at the right place the framework is not going to invoke it the way you want it so accessors are really important you have the access or to set the value on the access or to get the value and you can put code in there if somebody tells you they cannot put you cannot put can access so it's going to do a break or lose that's not true you can't put code in there but you have to be really careful when you put code in there is the story and why do you have to be careful because key value coding is actually relatively complex you have two ways of accessing euros and the frameworks we have are accessing the eros in these two different ways if you imagine you stack your view your database at the bottom and the new access and then you control and then the interface and world object so when you can move directly on thing yo-yo is sitting in the middle and the other one is changing your object because the user want to what you don't want is put some code in the to add any coding when you're fetching the objects probably not a good idea because when you're fetching a bunch of objects are with some performance it if you put some codes there for every object you're fetch or going to touch this code and reproducing over and over so strawberry you usually you don't put code in there on the other side when you use key when you're coding when when somebody is involved in your objects yet t-value coding and not stored key value coding you may do something like let's take a simple example you have modification date in your object and when somebody change the title of the bug it's changing the modification date in every in the when on the set title if you do set title on yo it's going to say creation modification that occurs now and put that into you so changing the title is actually changing two attributes but when you fetch the object from the database you don't want this set title method to be called and change your modification that you're not modifying the object is just fetching it so you have to understand how key value coding works and how key value cutting invoke those things in your object to know where to put your code so the first thing is T value cutting the user interface is accessing your object what is it calling in what order so the first thing a value cutting tries to find is a method with the name of your attribute you know name actually one that's missing on this slide everywhere everywhere you see name you can replace that by get name when Java so we supposed to get version also so it's looking for a method name get name or name and then is looking for the instance variable directly trying to access it and see if I can put something into this instance variable name name that's a bad name for natural good to explain wait it's named named okay I use the next thing and then key value coding still is trying to find a method name underscore name underscore get name and or an attribute name underscore name as opposed to this the set value are doing the same thing looking for a method name set name or the instance variable name name or after that and there is another in the way they're doing thing and the big difference between key value coding and store key value killing is that the order is different so we can show everything now so imagine you have your of your object and you have two meters on it when name name and the other one name underscore name if you are in TV decoding the one is going to be called is name if you want storable coding that's going to be underscore name and you can play with this thing you can turn them around something in product in web objects five is it's pure Java so all these methods need to be public if you want key value according to access your installs variable directly you better make it public if you are the top if your object is not in the package will find it we have ways to finding it but if you put your object inside the package and you make your yo-yo instance variable protected web objects has no way to access this thing when we were in Objective C with the bridge and stuff we are going from under you and just putting the value from there but we can't do that anymore we don't want to add some stuff in the VM to do that you know not clean so think about the the the the protected and public and private because it it's going to change the way your object access these they are in a package if they are not in a package don't bother about it it's just going to work like before exception box then private so nobody can access in which there are no package and protected not in a package and protected we can still access them you can change the way key value cutting is walking by implementing one of those method those are static method but we do some magic so they are inherited so if you can inherit this classic method but so you can say I don't want the frameworks to access to says my field directly I just want the framework to use the method never as a field and should use toward exercise which one no to this method there was no difference between key value coding and store TV recordings they all do exactly the key value coding thing there is no more study that you carry so you have your access ORS in your object and this the second thing usually put in your object of dilation you know when when the user change something in the in the interface you want to make sure that the thing is changing is correct so you write validation method there is multiple sort of validation method the first one is just waiting an attribute so in this case it's really bad but I think that tribute named named way whatever so you just write a method variate name taking a string because my name is a string and returning a string and the thing is throwing an exception and you just do whatever you want to check on this particular attribute and return the name if it's fine and for an exception and an S validation variation exception is there if there is any problem with the name so here I don't want the name of a component should contain more than four characters just a random rule that I made it this this method are actually codes automatically when you save your object there is something that's running around and checking all these things these are also called if you use web objects when you bang with web objects web objects is actually calling these methods she use a display group display group is also calling these methods but when you save it's called anyway so you have you sure that this thing can go to the database without being checked second kind of validation method its variation methods that take your world your object as a world so when you delete an object you here just doing something it's not very interesting validation but I'm just taking that and seen on the component and my component could have served components and I just want to make sure that you care you cannot remove the part you to removal the child first so you cannot suppress a component name if you have something so this is very that coordinate is actually the difference not taking any any value is just checking the euro object of the world it's not returning anything if it returned some sweet or nothing or throw an exception so validation by a value taking the value take the value return the value and throw an exception that's important because in in Java a method signature is actually the name of the method and the type of its arguments the type of the return value is not part of the signature so when we find a valid a method we don't know what this thing is returning so if you right away that matter that's returning void we're not going to notice and you're not returning anything so we're going to put null in your object because you returned void we don't know what to find this thing we put now and there is no really easy way to get out of it to make sure that you return something from a valid a attribute method the three methods for violating your object as a world very late or delete variate winter by dead for save I think they are self-explanatory by default very dead for insert invaded for save are doing the same thing in the three method although something missing on all these methods they are they all throw they all declare to throw an it's validation exception validation exception this is this three method something that's important is to call super because if you don't call super the valuation that's that set in your modifier is not going to happen because this isn't validate for save that the framework is actually going through all your attributes and saying very that name very they title validate something but something else so you have to call supers don't feel super all the validations that you have set in value that something is not going to be cold and all the variation that's in your modifier is not going to be cold either so that's the control to avoid of the method you can implement on your logic unable to set null for key if you have an attribute that's an integer we cannot put null in there so if we can put null we're going up we're just throwing an exception you should promote in able to set null for key you can do we can stop there and we're not going to throw if you compliment is method a work from in session when you insert a new object in an to an Indian context that's actually a place when you create a new objects the first thing you do even sorry when you insert the subjects there may be some stuff you want to put some default value in there you want to set up a creation date this is actually a method that's really useful that you can use all the time a way from fetch is once you fetch from the database the framework is going to call you and tell you a you've just been restored from the database you can you know set up some value in you and do some method you should probably not override are the two methods that are used for the bye-bye UF that will change and will read if you are if you're using use in your quick world universities those methods just so class and called stock value for key and calling automatically is to method if you're implementing custom objects you see these two methods before accessing an accessor you call will read and before setting of value you call will change that that tell the editing context looking at your object that something is about to change or we need to fetch data because it's going to need this data these metals are called really really really really often every time you access an attribute every time you set an attribute you call one or the two of them so those are expensive method use all over the place if you put cut in there and this code takes a little while to run because you want to do some I don't know something you're going to have performance problem right there because your fetch you can easily double the time you're taking to fetch a set of objects from the database by implementing freely of cutting there so that's why this is this method you probably should not overwrite them finally tip euros clean when you're writing you're allergic you you you can you know you can put your access code in there war framework code in there but if you if you don't keep your object clean if you put specific cut you access specific order war framework specific codes that means that you cannot use your logic anywhere else and with all these Java client technology maybe one day you will need to have them on the client-side and if you if you put whoa framework all in there you will never be able to take this thing and move it to the client side I'll make one exception for you access other utilities method that that you can use to to do some specific things you can use those because actually those are apparently new access but they are also in your distribution in a different package so you can actually use them in both places in but you have to be careful by the way you you use them if you use the same code in both places you can obviously so you have to so class and make the code using two different packages but that's the only exception that's okay you can use that's the only place where you can use you access specific code so that's the first part of a view of your code the code you're writing this is your access or your vacation and your business rules business rules are you know just occurred that you need on your EOS just going from one year to another and doing you know I want to I want to buy to buy a car of the car object I have the the buyer and I do all this saying that part of the business as part of a thing you do so these are the business for you can also implement in there in the you logic you can assume that everything is in the same editing context it's an important assertion because all your objects are tied together they are all in the same editing context with the exceptions of shared in context that should be completely transparent so everything in the same any context me I don't have to bother with an editing context and I should think about this one this other one you know you're all in the same meeting context and the first thing you do when you create one of these object you put it in your leading context so you know it's in there and you don't have you don't have to think about it this is not the place where you where you create new leading context where you move things from one to the other it's just everything isn't one anything context and you you just write your logic in there so that's the first that's the first part of the code you're writing the second part you probably expect that most of you are familiar with this this is your interface logic you know the thing you used to connect in web objects builder this is classic thing you have an array of bug and you have a Kronberg and you be the world petitioner right and you have the little comment here type in for saying that o in this NS array there is there is some bugs in there so this is just interface logic that you used to connect in any web objects builder when you build your application nothing really related to you F in there and it's just you have some arrays of object and you connect them you have the inside of an object containing a boolean value and you want to present a pop-up with yes/no that's also something that you do in your interface logic just transfer just transformation of view of your logic from one from one from one type to another just for display purpose so this go to the interface logic this should not go into your yo-yo should you know you know it's not because you have a boolean in your you that your brain should return yes or no as a strain it should rehearse which won't return the boolean not a string the string translation from the boolean to the string should be done in the UI so I pass I'll do it rapidly for the interface allergic the interface logic you have everything to connect in web builder you have all your translation from boolean to strings you also have in your interface allergic everything that's related to cessation classical session is the current user who's connected to the application that's a user you need when you invoke your business logic on your EOS right when you say when you have a user connected to your database and the users say ok I want to buy this piece of hardware that you're setting in your catalog you want to invoke the business logic with this user I want to say this user wants to guy this thing or this this user shopping card I want to add this in it so this is in the session and this is part of your interface this part of your application this is this is replication keeping this state natural you you just manipulating you and and your application is getting all these data there so what's what's missing in there you know I have my interface logic of my Year logic and I think it's it's time to tell you a little story about where do I put rice hopefully the customer is not in the room and we not say any names but I've been true to a customer site about six months six months ago and they had this nice application with table sort of other place in their world objects application with HTML table all over the place and every all the world components the world page was one component 6,000 line of code everything in there fetching rearranging you know an array that the swords were sorting everything within there and this was a fairly complex page with sorting all over the place you know you click and you sort and Riyadh and of course they call me because have some ones on performance program and the second thing is like everybody yes the requirements change and they needed the page in a different slightly different way and took them six weeks to do the page in a slightly different way and of course when we are done where they were recording will change again and that's approximately the time we have arrived to the customer site and look at the code and it was all monolithic out in one page you don't want that you don't want to put all your application everything that you do everything you fetch everything that you solve everything all these things you don't want to put that in your component right because it's too much even if you the people some people are so classing components I'm making components and subclassing the component and then so classical component and then reusing some patterns because that's already better that's already way nicer because you can actually reuse some of the code that's like we some nice concept then I told them that's not good place to put these things and you know it just went there for a day because I'm too expensive in the condom you know me for two days so I just went there for day fix is fixed on bugs here and there and tell them you know you think it's completely monolithic you don't want to put your code in your component put it somewhere else came back to the customer months after they moved all the code they put everything inside the EOS as this at that point I was you know you can put code somewhere else it's not because you have a component there and yo there they can put something something in the middle and then remind me of this of these classes I had when I was doing software engineering in school and saying you know you have this great thing coming from small talk it's called model-view-controller you know where this is exactly you have the logic your logic that's what that's your model right you have the interface logic it's where you put your interface that's yet your view right components use of you and you need a place to put your controller right so what I suggest is that you think you think about this I wrote a little application there that I want to show you after but and I'm going to make it available to you so you can look at it and and I'm interested by the feedback so where do you put the rice you put that in a controller layer but you can have everything so that's your application logic that's where you you fetch you save you we won't really cache on information because you know that you're going to need it at some other place this is the place where you deal with all these editing contacts you have also place nested not listed and another thing you can show you can support a back button that's working nicely this is the place where you do all your prefetching where everything that's everything that you do with us that's basically you'd want to do that in your controller I don't want to do that in your in your in your model and you don't want to do that in your interface I'm going to save my user story for the end so what are the advantages of having a controller that yeah you know dependent on your frameworks just to set of objects so placing Java Longo objects and and not touching anything in the frameworks just accessing ufufu access and you have metals and they are to build fresh specification to refresh restrictions or if the set of objects well you can reuse them on the client side all this logic that that potential is you know component on some of the place if it's just you know so class of an S or of any subject and no NS object anymore Java longer object there so class of object you can use it you can move it to the client side and you have to so class of object so actually you can test it without running your web objects application you don't have to have a wou component of a session or something you can just write some three lines of code and test the thing so what I want to show you now the little if I can have this screen on is this little application I wrote where I was in on the plane so I have here an application that's just a little simple application that's another bug tracker system I'm going to just to to run it I think I already compiled it so should just run it's coming there we go okay so it's just simple application where you can you can look in and search for bugs and and Oh run tests that's actually something that's really interesting is having all the tests available from the you interface when you're on development mode then you click on the button and running on your test so I'm going to to log in as power user on this thing that's highly really complex application so it's a really simple application you know you have you have users and what is it isn't doing okay you have user so you have the poor user they have a green thing and you can you know edit a user and you know just it's just direct web but whiskered plenty of line of code to do all this you can sort of course reverse sort and all these kind of things can go look at the component that exists in my database so you see that I'm submitting only bugs for book tracker and I can create new bugs so I wanted to do an application that was not just a demo but some things that actually work the this application is fully functional except for the search page because I do know that time to finish it fell asleep in the plane so everything else is functional that's why I'm not clicking on the search button because it's not the right thing but the idea is you try to save an empty bug is going to scream at you and telling you that you know you have to write this you write it you crazy so the validation thing you're running and I'm showing the right thing at the right place so how do I do that it's actually here we go so I split the application in four parts so we have our logic or UI logic and we have application logic and I also have one test thing we are right where I put all my tests actually I want to run the test because it's fun like when you test that's a good that's a good exercise that's a customer site we actually have the test you launch the applications running of the test and if one of the tests fail you cannot launch the application stop right there with the arrow and you cannot go further so we need to fix the test fix the the bird before you go further and actually we don't have any bug in the application so far because every time you find a bug we make a new test and you cannot launch your application till you fix a bug so guess what it's fixed in the day so this is just a simple thing that's running all my tests and if there was an arrow you have a back trace there and you click on this and you're going to you can see what line it is in your in your file and fix it right away so the Euro logic you logic there is nothing really in there it's just you know going to take a component component is simple in fact this we can see the code in there so a component as a very literal delete method that that check that you cannot suppress a component if you have sub component for it you cannot suppress a component is Everest bugs attached to this component the result of sort of I'd name it oh that I was looking for something so this is when I put on the under them on the slide just a simple validation method we also have a really big nice business logic they are asking the full name take the - honey you can cat a you take everything you go up the tree and you print the name with slashes and the race is just access so there is no really a lot of business logic in there now I think that in I'm going to advance in this application because I think I'm going to finish it now I'm going to add some something to move to move to change the states and things like that so I'm going to add probably more business logic in there state priority you know the state is just it's not an illusion or quicker but just could be no need for is the only thing nice about the state is there is access source we can just use them and then there is two classes in there that I put in my a logic because you know you don't know where to put them and they are actually really useful the first one is cheerleading context when you have you know you have a set of objects and then you fetch all your priorities in there and then you add a new priority and you want this thing to appear magically in your share it in context so that's what this subject is doing Elliott you look at the code because it's a maybe a little too long to explain here and I have another little class here that I use all over the place that's just bring me a static method thing object count with specification rectangle number so I don't have to redo it all over the place so that's basically my you nothing and they are really really really simple my user interface I have isoda them here we go I have a bunch of pages main page the component list page the component editor page user list user editor bug list buggy tutorial when I have an editor I'm using it for edit and also for new objects so it's just you know all the UI and when you look at one of these objects let's go look at the user list in there it's just you I glue there is really not a lot of saying interesting things in there you have the resubmitted can I delete an object and right now returning true because it's taking too much time to check so I can actually remove the method edit users just going to the next page reading the user delete user is just another page to just deleting the user and and passing in another page and new users just going as a page and creating an user but if you look at this code in there I'm never touching an user never or amusing user of controllers see edit user what I do is I create a page the user editor and I create a new user controller with the current user that's that is the crunches that someone is in my repetition so whatever I clicked and I in the next page I tell it set to user controller this is the controller I incur do your job and all the logic is in the user controller what is the user controller well that's nice third bucket that's in there so I have a controller basically what is the controller is something I don't like the name if somebody a good suggestion for a name and yes Model View controller but I don't like the name controller so I mean it may be a little difficult but a controller is basically a shell on top of an editing context is some things that's keeping it in context eventually creating a new editing context when you build one that can that's calling this hugely tease local instance of object my use taking three kilometers long and I made this smallest one and that's locking and unlocking your editing context and also asserting the locking locking is something you have to be aware of if you are writing a completely threaded application if you are if you only have one thread in the request response loop in Webber objects you don't really care about looking but it's nice to see how it's done that's why I put it in there so you can see how you can lock and unlock your editing context and having something that's running in all the cases nicely so let's see what I have as controller and I have a login controller that's just doing you know fetch with the fetch pacification to get to get the current the user and returning some error messages I have some simple controller what is a simple controller that's that's the controller that's basically taking care of one object when I was looking at the delete user I was creating a controller with the current user and telling it to delete that's basically a controller for this one object I can also create I can I also have this controller that our controller that are using a list of things so and finally it's a demo so first time you launch the application if the thing is empty it's filling in the feeling of the database with data fake data and then I have all my tests I want to insist on this because this is actually something that saved a lot of times because you know you you if you don't have the test if you it's a fact that you have all these controllers and you can test them by writing simple tests I'm going to choose which to write show you the login test in there you know test against just creating you're looking controller all set to use the name set the password and ask it for the user and if this thing blows up the user doesn't it's not there so I'm just asserting that this thing is working the right here or also at the right time and doing multiple things like this testing multiple cases this is really nice because imagine you have one of your developer that way we have this huge thing we need to add this feature and it's just starting to act into the code and write all these thing and commit it into CVS and that's it that's finished and then two weeks later you notice that well it broke something well if you have tests testing your controllers in all the different ways if you break something you're going to notice right away and actually this happen more often than you can think to is something that's happening really really orphan so I guess there is vomit I guess I'm there I'm sure I just want to finish with we can go back to the slide with my thing actually I'm going to go blank just a little story to tell you why I really think this thing is good add another customer site this one are doing these things right because they hired me to manage the project so this case on site we started building an application and we use this we use this these concepts and all the way and I told them you write test before you write your code yeah test now so we add test running we have everything running is so nice and then the the CEO of the of the company wanted to see a to show a demo of this application but he wanted to customize it because no look who we are using whereas to look for one of their customer and this is an application that has a different look they paid there they have people go into the customer site and customizing these applications to the different sites so they look different so in wanted the this application that's we started from scratch something like three months before you wanted the demo to shoot one of these customer of course we have anything ready this is just a short demo we had something running but it was with the logo of somebody yes so you wanted it with logo of the person and oh yeah and he wanted the current application they have this field in there that they don't have in there well basically wanted a completely different UI so we were well we cannot do that and then we we went for it we just you know we have to do it so let's do this this UI so we went in there and remove the UI and started from scratch with the UI and basically we did demo and we had to write something like six lines of code because everything was into controller and I didn't even think myself that it was going to work that well but actually everything is going to controller so all you have to do is actually wire stuff in web objects builder and that's it and that's a really really really powerful thing so I don't have to I don't have all the answers there is some stuff in this application I'm not happy with there is some some really glad I did it this way some stuff I don't really like that's why I didn't finish the search because I'm not sure that the search I did is great but even if it's a work in progress I want you to look at it I want really giving me feedback I don't guarantee that I'm going to read all the feedback okay probably going to read it but I probably not going to answer because I don't know many of you are in this room but issues all send me 10 emails I won't be able to read you to reply but I'm seeing tracing the feedback I quick if you can go back to this to the screen for a minute I've used the perfect some poor fool Apple technology in there so if she goes on on page that mac.com /uf there is this really nice page as I did with PageMaker where you can download this exact application that just showed you and a feel free to send me feedback feel free to send me any comments that you have I for trying to grade them if I can sign me flames if you want I read them too and okay back to the slides and that's basically all I had to say today as usual there is a lab downstairs 10:30 3:30 tomorrow go vote or webobjects there is a direct to advanced director to Java client just after this session you can and some other session web objects security I'm sure is going to talk fast in there and the feedback forum don't need the feedback from you we want your feedback and we to contact and I think this verb you