views:

105

answers:

3

Have you ever structured your source code based on your user interface parts? For example if your UI consists of:

  1. GridView for showing some properties
  2. 3D rendering panel
  3. panel for choosing active tools

, then you name and group your variables and functions more or less in the following way:

class Application
{
  string   PropertiesPanel_dataFile;
  DataSet  PropertiesPanel_dataSet;
  string[] PropertiesPanel_dataIdColumn;
  void     PropertiesPanel_OpenXml();
  void     PropertiesPanel_UpdateGridView();

  string   ThreeDView_modelFile;
  Panel    ThreeDView_panel;
  PointF[] ThreeDView_objectLocations;
  void     ThreeDView_RenderView();

  string   ToolPanel_configurationFile;
  Button[] ToolPanel_buttons;
  void     ToolPanel_CreateButtons();
}

What's your opinions on this? Can this architecture work in long run?

PS. Even though this solution might remind you of Front-ahead-design april-fool's joke http://thedailywtf.com/Articles/FrontAhead-Design.aspx my question is serious one.

EDIT

Have been maintaining and extending this kind of code for half a year now. Application has grown to over 3000 lines in the main .cs file, and about 2000 lines spread out in to smaller files (that contain generic-purpose helper-functions and classes). There are many parts of the code that should be generalized and taken out of the main file, and I'm constantly working on that, but in the end it doesn't really matter. The structure and subdivision of the code is so simple, that it's really easy to navigate though it. Since the UI contains less than 7 major components, there's no problem in fitting the whole design in you head at once. It's always pleasant to return to this code (after some break) and know immediately where to start from.

I guess one the reasons this gigantic procedural-like structure works in my case is the event-like nature of UI programming in c#. For the most part all this code does is implementation of different kinds of events, that are really specific to this project. Even though some event-functions immediately grow into couple of pages long monsters, coupling between event-handlers is not that tight, so it makes it easier to refactor and compress them afterwards. That's why Iam intentionally leaving generalization and refactoring for later time, when other projects start to require the same parts of implementation that this project uses.

PS to make it possible to navigate through 3000 lines of code I'm using FindNextSelection- and FindPrevSelection-macros in visual studio. After left-clicking on some variable I'm pressing F4 to jump to the next instance of it, and F2 to the previous instance. It's also possible to select some part of variable name and jump between partial-name matches. Without these shortcuts I would most defenetly lost my way long time ago :)

+1  A: 

That looks very procedural in concept and is completely bypassing the value of OOD. The sensible approach would be to create objects for each of your elements and the values you have given would be properties of those objects, i.e.

class PropertiesPanel 
{
  public string DataFile { get; set; }
  public DataSet DataSet { get; set; }
  public string[] DataIDColumn { get; set; }
  etc...

I think you get the idea so I'm not going to type the whole lot out. That's a first stage and there may be further work you could do to structure your application appropriately.

The best advice I ever received for OOD was to look to the smallest object that each logical branch of your app can be distilled to, it probably on has native types for properties (with .NET there no point in reinventing Framework objects either so they can be in your base class) and then using inheritance, polymorphism and encapsulation to expand on those base classes until you have an object that encapsulates the logical branch.

At the time I was writing an app that pushed data to an I2C device so I started with a class that put a bit onto an I2C bus, that was inherited by a class that put a byte onto a bus, inherited by a class that put an array of bytes onto the bus, and finally a class that put an address and an array of bytes. This is rather extreme OOD but it produced very clean code with each class being very small and very easy to debug.

It's possibly more work up front in thinking about the problem but in the long run it save soooooo much time it's just not funny.

Lazarus
Maybe it's just me, but somehow I fail to see success in OOD-teachings. Programming large systems is far from easy with it. I'm for one far from satisfied with how programming is done nowadays, and how large software system are reused and maintained.. be it OOD software or not...
AareP
Large systems are always difficult and will remain so but it is a little easier using OOD or any methodology that breaks the problem space into small, manageable chunks... that's the key.
Lazarus
A: 

It's OK to structure your user interface code based on your UI parts, but the non-UI related logic of your program should be kept separate.

But event on the UI part you shouldn't just smash everything into one class. Instead you should divide your UI code into several classes, so that every class only deals with one UI component and doesn't deal with others it doesn't need to know about:

class Application
{
  PropertiesPanel
  ThreeDView
  ToolPanel
}

class PropertiesPanel {
  string   dataFile;
  DataSet  dataSet;
  string[] dataIdColumn;
  void     OpenXml();
  void     UpdateGridView();
}

class ThreeDView {
  string   modelFile;
  Panel    panel;
  PointF[] objectLocations;
  void     RenderView();
}

class ToolPanel {
  string   configurationFile;
  Button[] buttons;
  void     CreateButtons();
}
Rene Saarsoo
A: 

What's your opinions on this?

It’s a mess.

Can this architecture work in long run?

No. (At least not without a lot of sweat.)

The names are insanely verbose. If you think about it, the long name prefixes are there to create a kind of separate ‘namespace’, to group related things together. There already is a better language construct for this very kind of thing – it’s classes. But the main problem is elsewhere.

User interfaces change often, concepts change seldom. If your code structure mirrors the user interface, you are locked to this particular interface. This makes reusing and refactoring the code quite hard. If you structure the code around the base concepts from the problem domain, you have a better chance to reuse already existing code as the software develops – the design will adapt to changes. And changes always happen in software.

(I hope that the ‘base concepts from the problem domain’ part is clear. For example, if you create a system for a local theater, you should base your design on the concepts of a Movie, Visitor, Seat, and so on, instead of structuring it around MovieList, SeatMap, TheaterPlan and such.)

Most of the time it is a good idea to decouple the core code from the GUI as much as possible (This is exactly what the Model–View–Controller design system is all about.) It is not an academic excercise, nor it is only required if the interface is going to change. A great example of decoupling the GUI from the rest of the code is the GUI programming on Mac OS X, with the Interface Designer, bindings and such. Unfortunately it takes a while to get into, you cannot simply skim the docs on the web and be enlightened.

zoul
As I commented to Lazarus same goes here. Just add MVC to the mix of tools that we are forced to use for the lack of better ones.
AareP
This is an opinion, not an argument (no offense). The design you propose has serious drawbacks from which I tried to mention a few in my answer. Object oriented design is not perfect (nothing is), but if used properly, it will result in far better design than the one you propose. Same goes for MVC – it is not a panacea, but it certainly has some good points and will help your design a lot, if you know what you are doing.
zoul
You are right, it's wrong to voice my opinions without proper arguments.. but for now my reputation score is so low, that it doesn't really matter. Just ignore me people.. :)
AareP
Reputation my foot :) Trying to invent something better and fail is the best way to appreciate the already invented solutions. So if our arguments did not satisfy you, just go on. Either you will really come up with something better, or you’ll fail and understand what’s good on OOD. Either way you win.
zoul