Improving code architecture?


  • 🚽 Regular

    Hopefully someone can suggest the best book(s) for this, the selection available on Amazon is mind-boggling.

    I'm self-taught except for a little ASM, C and Object Pascal at Uni during my EE degree and I'd like to improve the structures of my programs.

    I don't think I use OO features enough, and when I have multi-threaded things accepting data, processing and transforming it I struggle with synchronisation and juggling objects between different parts of the program. It just doesn't feel easy or polished enough once the programs get large.

    Any suggestions gladly accepted!



  • I think the thing that inspired me the most wasn't any sort of book, but this guy:

    He has about a hundred or so videos where he fires up vim and just goes on refactoring and messing around in rails and python. Even though I'm not using pretty much any of his technologies professionally (TDD, ruby, python, vim), it's really interesting to see first hand the way he thinks about code structure and patterns.

    Also, really impressive vim usage too. I mean, I'm an IDE guy and all, but looking at him, I can see why some people feel investing several years into mastering vim might be worthwhile.



  • I think Head-First design patterns might be the most learnifying book, but others might argue for something different.

    I think the more important thing is to consider the approach you are taking, as I wouldn't be surprised if you are coding to the user interface, rather than anything else.

    Do you end up with massive amounts of code in your UI backing classes? Do you have a class for each form in your application, and all your code for that form lives in that class? if so, you are probably making one of the more common mistakes.

    Ideally you want to write objects as if there is and never will be a UI, but the objects just do something. For example, if you are working with a CAN controlled device you might want to write a class that encapsulates all of the code for communicating with that device, say for example the device has traffic lights and a display or something, you would want to write code to provide simple methods like TurnGreenLightOn() and SetDisplayText(string) and so forth.

    with that done, you can then simplify the code higher up, without having to repeat that code everywhere, if you need to turn the green light on in 70 different places, its just TurngreenLightOn() rather than the 20 lines of code behind that method call to do it.

    "but Why do this in a seperate object? why not just have a TurnGreenLightOn() method on my forms?" you might ask. The reason is reasonably simple, what if you need to control 10 of those? how does your form tell the difference? you can have an array of identifiers or something and then just call TurnGreenLightOn(id) and it will work, but that gets pretty confusing. If you have a list of OBJECTS, then you can have those objects make it really clear what they are with other properties (a name, a location, an IP address, a port, a database record, and/or anything else you want) and then you can figure out exactly which object you want based on the current context easily.

    Apologies if I just told grandma to suck eggs. I have encountered code written without the above structure by engineers before in my career, so it is hard to gauge based on your post where your understanding is at, you might be doing everything I have just written already, in which case I may seem to be patronising you, but I promise not all engineers would find this unhelpful.


  • 🚽 Regular

    Thank you, it looks like a seriously wide area of 'development' is covered in those videos. I'll buy the first series and give it a go.


  • 🚽 Regular

    @algorythmics said:

    Apologies if I just told grandma to suck eggs. I have encountered code written without the above structure by engineers before in my career, so it is hard to gauge based on your post where your understanding is at, you might be doing everything I have just written already, in which case I may seem to be patronising you, but I promise not all engineers would find this unhelpful.

    Not at all. I do try and have defined layers with the UI layer being essentially optional.
    Most of my stuff is Windows services with no UI, I generally have to send and receive data and requests from TCP sockets, transform it and store it in a DB. Sometimes a self-hosted web service as well.

    I just seem to end up with a lot of explicit state-management. It's hard to explain without posting code but I think if I structured it better it should be easier (like you said, context). It's the conceptual side I think I need to work on.

    @algorythmics said:

    I think Head-First design patterns might be the most learnifying book

    I'll give that a go, thanks!



  • @Cursorkeys said:

    I just seem to end up with a lot of explicit state-management. It's hard to explain without posting code but I think if I structured it better it should be easier (like you said, context). It's the conceptual side I think I need to work on.

    Is there a reason that you end up needing to have state? Over-dependence on state is sometimes an indicator of a messy design.



  • @algorythmics said:

    I think the more important thing is to consider the approach you are taking, as I wouldn't be surprised if you are coding to the user interface, rather than anything else.

    There's nothing wrong with that.

    @algorythmics said:

    Do you end up with massive amounts of code in your UI backing classes?

    ... that, however, is a problem.

    I don't know. I'm not "qualified" to give advice as I'm self-taught, too. But then again, I work with a lot of people who aren't, and can't code their way out of a wet paper bag. So I've never seen "self taught" as a limitation.



  • @Cursorkeys said:

    I generally have to send and receive data and requests from TCP sockets

    This also sounds fishy. There are so many existing containers that will provide a communications path for you that it's rare to have to assemble packets yourself. Can you elaborate a bit on what you are doing?



  • BTW, also consider that a bigger risk than not having enough abstraction and architecture is having WAY TOO MUCH. There's a lot of value in simple code that does exactly what it says in a straightforward way.



  • @Jaime said:

    There are so many existing containers that will provide a communications path for you that it's rare to have to assemble packets yourself.

    ... who said he was assembling packets? WTF, where did that come from.



  • @cartman82 said:

    Also, really impressive vim usage too. I mean, I'm an IDE guy and all, but looking at him, I can see why some people feel investing several years into mastering vim might be worthwhile.

    I'm going to check out the series for this, because hopefully it'll enlighten me about how vim isn't just a dinosaur prototype of a crap version of Sublime.



  • It isn't but its easy to fall into problems, I guess I used coding to the user interface in my first quoted sentence, as a euphemism for the second quoted sentence.

    I was referring in the first instance to the practice of building a user interface, then creating the events for all the objects in that user interface, and then writing the code to handle those events all in the one class. If it was a pattern you wanted to encourage you might refer to it as "UI focused development". It is arguably object oriented because each page/window of your UI is on object, but it's really badly not because the concept of single responsibility and separation either gets ignored, or encourages you to write a terrible UI with bits all over the place.



  • @blakeyrat said:

    ... who said he was assembling packets? WTF, where did that come from.

    Because if you're using an existing protocol, then you rarely call what you are doing "TCP Sockets". Sure HttpRequest works over TCP, but no one would refer to using it as "send and receive data and requests from TCP sockets".



  • @Jaime said:

    Because if you're using an existing protocol, then you rarely call what you are doing "TCP Sockets". Sure HttpRequest works over TCP, but no one would refer to using it as "send and receive data and requests from TCP sockets".

    So... it came from the depths of your own twisted mind or, in other words, you made it up. Gotcha.

    "YOU MUST BE DOING IT WRONG!@!!!!!" "Why do you say that?" "WELL I DON'T KNOW YOU ARE BUT YOU'RE USING SLIGHTLY DIFFERENT TERMINOLOGY THAN I'M USED TO!!!!@!$!@"



  • @blakeyrat said:

    So... it came from the depths of your own twisted mind or, in other words, you made it up. Gotcha.

    @Jaime said:

    This also sounds fishy. There are so many existing containers that will provide a communications path for you that it's rare to have to assemble packets yourself. Can you elaborate a bit on what you are doing?

    I only mentioned it sounds fishy and asked a follow up question about the possibility since the language he used contained a hint that he might be assembling packets. I never suggested that I knew that is what Cursorkeys was doing. You are the one who made that fact up.


  • Discourse touched me in a no-no place

    @cartman82 said:

    He has about a hundred or so videos where he fires up vim and just goes on refactoring and messing around in rails and python.

    Programming Let's Plays? Bizarre!



  • @FrostCat said:

    Programming Let's Plays? Bizarre!

    Not exactly. Each episode has a specific point he wants to demonstrate. They are just not a part of some huge overarching course or lesson plan.

    @hungrier said:

    I'm going to check out the series for this, because hopefully it'll enlighten me about how vim isn't just a dinosaur prototype of a crap version of Sublime.

    I'm pretty sure he's practicing before he starts recording. On the other hand, I don't think I could beat him with any amount of practice beforehand.



  • This statement is fucking important. Read it again, then a third time.


  • 🚽 Regular

    @Jaime said:

    Is there a reason that you end up needing to have state? Over-dependence on state is sometimes an indicator of a messy design.

    You're right. Some parts of that particular project started to suffer from inside-out-itis. One I caught and refactored was having a group of objects with a flag in each object for participation in a particular process. That meant the group had to be iterated during processing to check the flags when having a collection of the id's of the participating objects in the controller doing the processing seemed a hell of a lot saner.


  • 🚽 Regular

    @Jaime said:

    This also sounds fishy. There are so many existing containers that will provide a communications path for you that it's rare to have to assemble packets yourself. Can you elaborate a bit on what you are doing?

    I have to talk to a large set of RTE that speak a binary protocol over TCP that I didn't design.

    I inherit from BinarySerializationProtocol for my messages. There are a few types of message I can send/receive.
    Because one complete message comes in from my RTE in chunks (possibly hours apart or just milliseconds) I have a 'ConnectionServer' class that uses Net.Sockets.TcpListener, when connections arrive I spin up a thread for each with an Net.IPEndpoint and a MemoryStream to hold the data. When data arrives it gets checked for a valid header, the expected length etc... and when completly assembled a CRC check is done and the main program is notified that valid data is waiting. There's a bit of housekeeping, error management and cleanup stuff wrapped around all that.

    That seemed to be the best way to do it?


    @Matches said:
    This statement is fucking important. Read it again, then a third time.

    Yeah, I was very guilty of that after I learnt about the Factory pattern. I quickly saw that abstracting everything just generated a lot of rather sparse classes that were annoying to navigate.



  • If you use WCF and write a custom serializer for it, you can get rid of all your infrastructure code. Here is an example of using WCF to speak the RADIUS protocol.


  • 🚽 Regular

    Thanks, I'll take a close look at that. I'm a fan of WCF, it's nicely designed.


  • Discourse touched me in a no-no place

    @Cursorkeys said:

    I'm self-taught except for a little ASM, C and Object Pascal at Uni during my EE degree and I'd like to improve the structures of my programs.

    I don't think I use OO features enough, and when I have multi-threaded things accepting data, processing and transforming it I struggle with synchronisation and juggling objects between different parts of the program. It just doesn't feel easy or polished enough once the programs get large.

    The real key to getting a good design is to ensure that each class has a well-defined function that you could summarize in a single sentence without resorting to lame-ass excuses like “does stuff to the whotsit”. What it does and why you would be using it should be obvious, and it should do just what is necessary to achieve that high-level description (and it might do it by delegating some of the tasks to other objects; delegation is the most important OO pattern, more so than even inheritance). It's very much like writing a good function or a good method, except with a class you've got to think about the encapsulated state as well.

    When picking where to split things, key things to look for are shared contexts, security domains, roles, that sort of thing. You probably need to read some of the mass of works on OO analysis and OO design; books of software patterns tend to be at the accessible end of this, but the theoretical side gets very UML-heavy and is usually conducted at a rather high level of abstraction.

    And remember this: you're also looking to keep things as simple as possible. A good design is one that simplifies the problem instead of making the complexity grow like cancer.


  • ♿ (Parody)

    @blakeyrat said:

    So I've never seen "self taught" as a limitation.

    I agree, so long as you're continually learning new things and understand them. But I'm biased that way, too. I usually know patterns before I learn the name for them (some I figure out on my own and I pick others up from looking at others' code).


Log in to reply