1. OCAU Merchandise now available! Check out our 20th Anniversary Mugs, Classic Logo Shirts and much more! Discussion here.
    Dismiss Notice

Help me become better at coding large programs

Discussion in 'Programming & Software Development' started by Foliage, Dec 9, 2010.

  1. SaTaN

    SaTaN Member

    Joined:
    Jun 18, 2002
    Messages:
    4,790
    Location:
    Caulfield-ish
    pretend each .c file is a class, then the normal OO rules apply. Each .c should only do one logical thing, and everything in the .c should fiddle with the same data.

    Any functions or globals which are "private" shouldn't be declared in the corrresponding .h file. If they can be marked "static" then excellenant because the compiler will then warn you if they arent being used.
     
  2. deepspring

    deepspring Member

    Joined:
    Jul 8, 2002
    Messages:
    3,601
    Location:
    Maitland, NSW
    Ah now I'm starting to understand.
     
  3. Lukenet

    Lukenet Member

    Joined:
    Oct 4, 2002
    Messages:
    535
    Location:
    Brisbane
    I don't know if anyone still uses UML, but when I was at uni, I found it a good way model your classes if you are having problems with larger programs. if done correctly, it almost writes your classes for you without missing any of the required functionality.

    I don't know if anyone uses this in the real world, but it may be worth a look for you, especially if you are writing large classes.

    I was always told to keep my classes as simple as possible for reuse. I am a lazy coder, I like to write and reuse classes I have written in the past, so I keep them quite focused and single function ish.. I do have lots of classes, but they are very hierarchical so I grab whole parent classes for later reuse.
     
  4. the-enigma

    the-enigma Member

    Joined:
    Mar 18, 2002
    Messages:
    1,728
    Location:
    BrisVegas
    Someone who speaks sense!

    Being "good" at developing large programs, I've found, is largely independent of your choice of language, or IDE, or anything like that. It's more about good development practices. In particular, my choice of words here points to the solution. Small projects can be "coded", but with larger programs/projects, you need to develop. You need to sit down and work out what needs to be coded, what classes you need, what each class should do, and you should ideally be doing all of this before even touching any code.

    I did quote a post about UML, and I rarely use "strict" UML, but drawing diagrams can really be useful to show any sort of hierarchy that may be useful.
     
  5. OP
    OP
    Foliage

    Foliage Member

    Joined:
    Jan 22, 2002
    Messages:
    32,085
    Location:
    Sleepwithyourdadelaide
    Absolutely true.

    I've been putting this stuff to use the past week with a small threaded GUI app I've been programming, didn't need to be threaded but I wanted to learn something new and split everything up properly.

    Only 3 classes as all it really does is convert a html help system to wiki markup, then upload the wiki markup to a wiki server, but I did both processes in seperate threads so it can upload whilst converting (which is much faster than uploading). Also means the GUI responds properly whilst doing so.
     
  6. SaTaN

    SaTaN Member

    Joined:
    Jun 18, 2002
    Messages:
    4,790
    Location:
    Caulfield-ish
    sounds like you've actually done the right thing for the wrong reason... The absolute worst crime commitable on a GUI program (other than outright crashing) is causing the UI to lock up while waiting for *something* to happen.

    Also oblig http://xkcd.com/844/
     
  7. OP
    OP
    Foliage

    Foliage Member

    Joined:
    Jan 22, 2002
    Messages:
    32,085
    Location:
    Sleepwithyourdadelaide
    I did it to stop that happening! If I ran everything in the UI thread at once then it did exactly that. Now the UI still works whilst it starts processing files (updates the log on the screen) and the user can manually add files to a queue and also upload files if needed. So I was wrong, it is actually 3 threads.

    I don't actually know how to run intensive processing code behind a GUI without making it lock up without using threads. How would you do it? In C# starting new threads is very simple and a simple delegate is used to update the GUI whilst it is doing so.

    The conversion process can take minutes to hours with a reasonable amount of data.
     
    Last edited: Jan 10, 2011
  8. SaTaN

    SaTaN Member

    Joined:
    Jun 18, 2002
    Messages:
    4,790
    Location:
    Caulfield-ish
    Pass :) I havnt done any gui coding in years, but yeah pretty much, C#/java make it nice to fork off a thread to do some work and wait for it to finish
     
  9. OP
    OP
    Foliage

    Foliage Member

    Joined:
    Jan 22, 2002
    Messages:
    32,085
    Location:
    Sleepwithyourdadelaide
    I honestly don't think there is a way to do it properly without threads.
     
  10. mikeyyy

    mikeyyy Member

    Joined:
    Apr 7, 2005
    Messages:
    590
    Location:
    Sydney
    Continuations, non-blocking operations / asynchronous io.

    The idea is you keep executing in the same thread until you reach a blocking operation such as a disk read or network access, at which point you kick off the long-running operation, save somewhere any state you'll need when the operation finishes (perhaps save it to a list of pending disk jobs), then just return.

    The event-loop that drives the GUI, is completely generic, and allows handling of any events, such as DISK_READ_FINISHED (completely made up). Upon receiving this event, you lookup your list of pending disk jobs, find which one it is, then do whatever it is you wanted to do after doing the read(). The state you saved might include a function pointer (the continuation) to do this, or if your program only does one thing with disk reads, you can hardcode it. Again, if this has any long-running operations, it'll kick it off and go back to the event loop. This should result in better performance on a single-core machine since you don't have the overheads of context-switching between threads, though quad cores are the norm now. :)

    It can be a bit confusing at first, but it can be worth it to completely avoid the race conditions that comes with multi-threading.

    ninja edit: You need OS support for asynchronous i/o to do this. One example would be on Linux, using select() to watch for user input, and a file read at the same time.
     
    Last edited: Jan 10, 2011
  11. OP
    OP
    Foliage

    Foliage Member

    Joined:
    Jan 22, 2002
    Messages:
    32,085
    Location:
    Sleepwithyourdadelaide
    Interesting, I've been seeing those terms more and more with my reading, will have to do some more! This is probably my first decent attempt at threading as I figured it was a very simple app so it should be fairly easy to keep it that way even with threads.

    I don't know if you've coded in .NET before, but what would be the best method for doing intensive processing in a GUI app without using threads and using the methods you've mentioned? From what I've read it is all message based and there is no main loop as such, so I am not sure how I would handle a state machine in a main loop like you've mentioned.

    I've coded a few solutions in C on PIC microprocessors in a similar way, main loop that does operations based on states and it works very well, just not sure how I would implement it in a language like .NET with a gui, or how I'd do it neater/simpler than I currently have either.
     
  12. mikeyyy

    mikeyyy Member

    Joined:
    Apr 7, 2005
    Messages:
    590
    Location:
    Sydney
    Yeah I've used VB.NET and C#.NET before. Even if you can't see it, behind the scenes the C# GUI app will have a main event loop. It will receive messages like input, and then it will execute a callback in your code (KeyEvent?). Or for example, you set up a timer, when the Interval expires, the event loop receives a message from the OS, and in response it looks up the timer object and calls your timerExpired (or whatever it's called :)) callback. An example of how it might know which timer callback to call is, it might just check all active timers and manually loop through and see if each one has expired, and it will call callbacks for every expired timer. Alternatively the call to setup the timer notification registration might take in an opaque value which could be a pointer to your timer object, and every timer notification gives you the opaque value back which you can just typecast.

    The fact that it's already completely event-driven makes avoiding threads easy. I'll see what I can dig up, but after dinner.
     
    Last edited: Jan 10, 2011
  13. Mikos

    Mikos Member

    Joined:
    Mar 12, 2004
    Messages:
    2,855
    Location:
    Cydonia
    You're GUI (form.cs) class should only have "hookup" code really. You shouldn't be bothering trying to think "how can I do all this in GUI code without threads" because it's really a bad way to do things. Use the threadpool (ThreadPool.QueueUserWorkItem()) to fire off background threads and then hook up the GUI to events off your classes to change when things happen.

    Using threads may seem complicated but it isn't too bad. Once you get confident enough to build thread-safe code & understand how to communicate between threads with events or common objects, it's a beautiful thing. You end up with programs that generally scale very well with number of cores available. A few months ago I wrote an app that would run on an i7 with all cores at 100% for hours doing processing, it was awesome to watch.

    There is only 1 UI thread, so unless you are doing a 100% synchronous program where everything executes in the UI thread, the program HAS to be using threads. Even if you are using async methods on some 3rd party library, those async methods will invoke background threads.

    Anyway take it slowly, it takes years to understand it all. Start with the basics and get your OO skills down pat, learn some interesting design patterns, build some basic programs. Then start tinkering with some network socketing code and parallel processing.
     
  14. mikeyyy

    mikeyyy Member

    Joined:
    Apr 7, 2005
    Messages:
    590
    Location:
    Sydney
    Just some more background. In the main function of your C# GUI app, you probably have an Application.Run(). I think this is what enters the main thread into the event loop. Calling Application.Exit() will queue an event for the main loop, when it processes it, it will break out of the loop and return from Application.Run().

    Meanwhile, searching up on asynchronous io in C#, it looks like Steams have a BeginRead() method you can use, and you pass in a callback. It will handle all the dirty work for you. All you have to do is finish off the rest of the work in the callback. So instead of having 1 function that does your entire thing as you normally would, you might end up having several that all perform different segments. Instead of using local scope and the stack, you'll need to save the data you need. I think BeginRead lets you pass in an object that it will pass to your callback, i.e. your saved data.

    So for example, say you want to add up the first 10 numbers in a file and write the result to another file, you start the process by clicking a button. Under a button click you might have 'startWork()' which begins a disk read from a file, you pass in a callback called 'processFileAndBeginWriteback()'. It parses the file buffer into 10 integers, and adds them up, then begins the write to the output file, you pass another callback 'finishWriteback()' to this BeginWrite() call. In finishWriteback(), you can update a label/textbox saying 'success!' or something. When the input file is being read, or the output file is being written, you'll be sitting in your event loop waiting for a message/event.

    If you want I can write up a demo app.

    Sure threads are great if you have the cores to utilise them, but that's not always the case. If you want to write high-performance code for mobile phones (or embedded systems in general), a lot of the time you have only one core and threads will slow you down (but also will make the code much more readable. :p) If you have 10 i/o requests you want done at once, you'll need 10 threads. If you do it asynchronously, you still just need only 1 thread.

    Though last I heard phones will be going multi-core soon enough. Then you need to observe whether you need raw performance, or is running on one core good enough? If one core is idle you can shut it off for a substantial power saving.

    Also it's not necessarily true that you MUST have background threads. If the OS is a single-threaded model, it will do the same thing. It will execute until it hits the disk read operation, then while it waits for the result via hardware interrupt it can schedule another (perhaps lower priority?) thread in the system that may have nothing to do with your program.
     
  15. OP
    OP
    Foliage

    Foliage Member

    Joined:
    Jan 22, 2002
    Messages:
    32,085
    Location:
    Sleepwithyourdadelaide
    If you've honestly got time, that'd be great. Thanks for all the information, I'll have to do a few basic demo apps myself to see if I can figure it all out.
     
  16. SaTaN

    SaTaN Member

    Joined:
    Jun 18, 2002
    Messages:
    4,790
    Location:
    Caulfield-ish
    Woah. Threading and thread workers *is* the correct way to do stuff in the background :)
     
  17. OP
    OP
    Foliage

    Foliage Member

    Joined:
    Jan 22, 2002
    Messages:
    32,085
    Location:
    Sleepwithyourdadelaide
    Last edited: Jan 10, 2011
  18. Mikos

    Mikos Member

    Joined:
    Mar 12, 2004
    Messages:
    2,855
    Location:
    Cydonia
    There are already dual core phones on the market, I believe the snapdragon is a 1GHz dual core? Anyway the days of single-cored items are short lived. Intel already have 64 or 128 (can't remember which) core proof of concept processors around, you will see these in mainstream servers and PCs within the next few years no doubt. There will always be a niche market for single-thread optimised code but I don't see it being a big market in the future.

    If you really want to get ahead of the game read up on job or task orientated programming. It will be the next advancement most likely to make parallel programming easier and more efficient.
     
  19. mikeyyy

    mikeyyy Member

    Joined:
    Apr 7, 2005
    Messages:
    590
    Location:
    Sydney
    While working on the asynchronous file i/o demo code, I came across a snag. The callbacks for BeginWrite() and BeginRead() are executed in a separate thread (I printed out the thread ids), damn you .NET! They really don't need to be, I'm trying to see if there's a way to do asynchronous reads and get callbacks executed in the GUI thread (as is done when you click a button on a form).
     
  20. Mikos

    Mikos Member

    Joined:
    Mar 12, 2004
    Messages:
    2,855
    Location:
    Cydonia
    If they weren't executed in background threads, they'd lock up the UI thread until they completed. You'll have to use a .Invoke most likely on a UI object to get a method to run on the UI thread. Generally you want to avoid the UI thread at all costs because whenever something is running in it, the UI locks up for that time and makes user experience very bad!
     

Share This Page

Advertisement: