Composite contents = new Composite(parentComposite, SWT.NONE);
contents.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout layout = new GridLayout();
layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
layout.numColumns = 2;
contents.setLayout(layout);
Label label = new Label(contents, SWT.LEFT);
label.setText(WorkbenchMessages.FileExtension_fileTypeLabel);
GridData data = new GridData();
data.horizontalAlignment = GridData.FILL;
label.setLayoutData(data);
filenameField = new Text(contents, SWT.SINGLE | SWT.BORDER);
data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.grabExcessHorizontalSpace = true;
filenameField.setLayoutData(data);
Whenever there is a low-level way of doing things, you can come up with a higher-level way and reduce the code size. Of course, you are only reducing the overall code size when the higher-level abstraction is used widely enough to amortize the cost of its implementation. In our SWT layout example, you could write instead:
Composite contents = new Composite(parentComposite, SWT.NONE);
contents.setLayoutData(new GridData(GridData.FILL_BOTH));
new Label(contents, SWT.LEFT).setText(label);
filenameField = new Text(contents, SWT.SINGLE | SWT.BORDER);
Point defaultMargins = LayoutConstants.getMargins();
GridLayoutFactory.fillDefaults().numColumns(2).margins(
defaultMargins.x, defaultMargins.y).generateLayout(contents);
Now this is looking a lot shorter, and maybe even more elegant. However, even if GridLayoutFactory is used widely enough to amortize the additional footprint caused by its implementation, there are still two problems: first, the original code ran faster, and second, you now have to learn two APIs - the higher-level one, and the lower-level one when the abstraction gets in your way.
You can see where I am going - there is no clear cut solution to this. It is really a hard problem, and in many cases, we will have to trade off one of the factors disk size, memory size, CPU consumption against the others.
The difference in code density between various languages is so great that often less memory is needed to hold both a program written in a "compact" language (such as a domain-specific programming language, Microsoft P-Code, or threaded code), plus an interpreter for that compact language (written in native code), than to hold that program written directly in native code.
So if we had a domain-specific language for creating SWT widgets and specifying their layout, we could get away with no Java code at all! I don't know if the .class file is a space efficient encoding for SWT widget hierarchies and layouts, but even if it is, consider this: The byte code for creating the widgets will stay in memory for as long as its class is referenced. Chances are that this will be a very long time; at least for the time that particular part of the UI is materialized somewhere. By comparison, if we had a domain-specific language, it would have to be read once to create the widgets and layout, after which the memory could be freed.
So maybe we can have our cake and eat it too! After thinking about this a bit, I am all excited about using cool new technologies, as long as they don't cause bloat.
We also have to be very carfeful not to use multiple redundant technologies to achieve the same thing, because that is another source of bloat. As in, for example, letting everyone plug in their favourite domain specific language for creating SWT widgets and layouts. This kind of redundancy would be just as bad as redundancy through repetitive boilerplate code, so let's pick one way of doing declarative UIs!
Note that there are lots of other sources of bloat, for example, unneeded functionality, too many layers of abstraction, or unnecessary flexibility. I am running out of time but it is probably interesting to think about these as well. I'd like to know if you have any pointers for me in the comments!
If avoiding bloat is one of the goals of e4, we need to keep this goal in mind all the time. Every bit of functionality should be pulling its own weight. For example, do not add convenience API unless its additional weight can be justified by reduced weight somewhere else.
I believe we should start watching our weight from the very beginning, and from time to time, it is probably healthy to discuss the weight of the various pieces. I can't wait until we have some kind of continuous build in place, so that we can make it visible for everyone how big (or small!) the components are, and how they are growing (or shrinking!) over time.
We could also borrow some ideas from the business world and introduce budgets. You want to provide a component for declarative UI? How about you get an allowance of 300 K? Would that be enough?
What do you think?