blogsMoaningAboutJSP.add(
Blogger.getInstance("http://ianso.blogspot.com")
.createBlankAnnoyedProgrammerEntry()
);
So anyway, although I do realise that JSP came a long before MVC was applied to webapp development, but WTF is a templating solution doing setting the MIME type on my response?
This is not even taking into account the stupid, stupid, requirement to compile JSPs into Java files and then Java classes, meaning that there are twice as many places for compilation errors, and twice as many places for logical errors, and a PIA to write a decent IDE for, Hell! JSP is never a good idea. But it's standard.
2005/11/24
Ingredients for a seamless iframe with no border in IE6:
In most webapp development, you don't want to draw attention to your techniques - iframes are a good example, you don't want a "look ma, a page within a page!" feeling, you just want it to display and look & feel like the rest of your app.
In FF this is easy: the CSS is "iframe {border:0;}". Naturally, this also applies to stuff you add to the DOM via scripting.
In IE, it's a complete pain in the ass, as usual. Not only do you have to set the old-style "like it's 1999!" attributes as follows:
iFrame.setAttribute("border", "0");
iFrame.setAttribute("frameborder", "0");
you also have to set the style on the body of the iframe you loaded, as follows:
body {border:0;}
As if there was any other circumstance in which the border style of your body affects the container. Grr.
In FF this is easy: the CSS is "iframe {border:0;}". Naturally, this also applies to stuff you add to the DOM via scripting.
In IE, it's a complete pain in the ass, as usual. Not only do you have to set the old-style "like it's 1999!" attributes as follows:
iFrame.setAttribute("border", "0");
iFrame.setAttribute("frameborder", "0");
you also have to set the style on the body of the iframe you loaded, as follows:
body {border:0;}
As if there was any other circumstance in which the border style of your body affects the container. Grr.
2005/11/18
More IE quirks: "This page contains secure and non-secure items. Do you want to display the non-secure items?" when using iframes in https web-pages
This one is more google-able than the ones I've noted down below, but anyway: the gist of the issue is that iframes loaded into a secure page with an src attribute of "" (an empty string) or missing, or "about:blank", are treated as insecure.
This is done when the iframe is going to be filled dynamically via javascript or equivalent.
Since network sniffing doesn't show any non-ssl HTTP requests, this one might be a bit of a pain to debug, were it not for the users of a a wysiwyg/textarea replacement project who reported the problem on their forums.
Anyway, the solution is to use src="javascript:;" as an initial value, which is apparently secure enough for IE not to throw an error message in the user's face.
1/12/2005: This also appears to happen with <object>s, with a codebase that is not https, and that sucks.
This is done when the iframe is going to be filled dynamically via javascript or equivalent.
Since network sniffing doesn't show any non-ssl HTTP requests, this one might be a bit of a pain to debug, were it not for the users of a a wysiwyg/textarea replacement project who reported the problem on their forums.
Anyway, the solution is to use src="javascript:;" as an initial value, which is apparently secure enough for IE not to throw an error message in the user's face.
1/12/2005: This also appears to happen with <object>s, with a codebase that is not https, and that sucks.
2005/10/28
The world is beautiful place to be born into...
Read this.
Best heard read in "unforscene - the world is", and is (like life itself) both uplifting and depressing. Yay.
Best heard read in "unforscene - the world is", and is (like life itself) both uplifting and depressing. Yay.
RoooooaR!
Crushing all in it's path
So it's become increasingly evident to me that the the hour at which Ruby on Rails proceeds to stomp all over 80-90% of all Java webapp development is coming closer and closer, if it hasn't got here already.
As a developer, who's been online for ages and a computerphile for even longer, seeing whole fields of technology and millions of man-hours of work obsoleted in a period of months is something I've seen over and over again, so I knew it would inevitably happen to my own sub-sub-field.
And so, as a Java webapp developer, this necessarily requires a response, such as (for example) moving to RoR myself. I can do that if I have to, no problem, in fact I'd kinda look forward to it.
However, I'd like to make one thing clear: to anyone who claims that RoR can do things Java can't, I would politely request that they renew their acquaintance with the concept of the 'Universal Turing Machine', and then come back an re-examine those claims in the light of their newfound knowledge.
</snide>. Myself, I've also seen plenty of reaction from the world of Java, starting with things like Trails and Sails, and continuing with the various solutions that have been welded ontop of existing frameworks.
However, this is not enough to prevent Java's obsolescence in this field. All these solutions so far have been reactionary, and while it's good that the world of Java can readily admit influence from outside sources, all these solutions, by virtue of being copies or tributes to the original, cannot help but serve as a mere reflection of the power of the original.
(It's also worth noting that Python, Perl, Lisp etc. all had their Rails knock-offs months before Java did.)
Firstly, there are interesting ideas that don't exist in RoR. Of all of these, the most interesting by far is continuations.
Put simply, Spring Web Flow and Apache Beehive both encapsulate page-navigation workflow through the construction of state machines, similar in principle to directed state graphs, and influenced to a certain extent by JSF. [Web Flow does actually support continuations, I've just discovered.]
This is one way of expressing logic. However, logic is far better expressed in (guess what) a full-featured programming language, which will always be richer than any configuration file. This is what continuations should be used for. Construction of wizards, guides and sub-sequences could hardly be more natural.
Secondly, the (at least) two areas in which RoR is indisputably king is in inferring webapp structure from database structure, and in the all-important zero-turnaround time. Neither of these are impossible to do in Java, but I'll take them in turn.
Firstly, ActiveRecord. What is it that RoR does? Simply put, it makes the database the 'center of authority' (CoA) for the structure of the web-app. It infers what it can, which is usually 90% of what is needed, and lets the developer add the finishing touches.
Trails is similar in that it uses the business object model (BOM) as the CoA, and uses that to generate both the persistence (database) and the frontend webapp. This is in keeping with the Java view of keeping the semantic discussion at the object level instead of the DB level.
However, Trails also requires you do use annotations, which assumes that you have control over the source of your BOM, which in many cases isn't true (SOA-based methodologies can mean that you're simply the client of a different division, and that your BOM is generated from WSDL/XSD). This isn't a problem, Trails could just as easily use reflection to infer all the stuff that the tags point out to the framework.
Secondly, zero-turnaround time. Template-wise, Java already has this because JSP is recompiled when the source file changes. Personally however, I think JSP (1.x) sucks, and the whole idea of compiling markup templates into .class files is braindead, so I won't rely on this example too heavily, but nevertheless it proves my point.
WRT. zero-turnaround Java, in the traditional webapp this is of course not possible, but (a) this assumes that Java is your workaday language, whereas in fact it's entirely possible (and often desirable) for other languages such as Groovy, Rhino etc. to provide the meat of the application, for this very reason among others, and (b) you're not using something like Janino, which effectively provides the eval() function, and then some, to your normal JVM. (At a cost of course, but that's what facades are for.)
Yet another framework?
Which brings me to my point. If Java webapp development is not just to survive but also to thrive, reacting to RoR is not enough. It must also leapfrog RoR in the metrics by which RoR judges itself.
You can stop laughing now.
It's OK, I'll wait.
This in itself is fairly simple. So far people have been expressing web-development in lots of different languages, some (such as Ruby) more sympa than others (Java), but all of them, even JavaScript, when it comes down to it are not webapp-native languages.
For webapps, when it comes down to it, the language is very simple. There are four verbs: Create, Read, Update, Delete (CRUD). Your set of base nouns is defined by your database, or your object model, where-ever you put your authority. You derive nouns by operations on your base nouns. Each noun can have the four verbs applied to it.
This is all you need for webapps. The rest is reporting - list views, summary pages, query interfaces, etc. In an SOA environment these are simply other services, so that's easy for me, but I imagine other solutions would have to be found for this.
Thus the whole issue is resolved to three domain-specific problems: how to derive nouns, how to customise templating, and how to customise verbs.
(The typical Java response would be to have three different XML config files. Grr. Me, all my config files are generated via xDoclet and other fiddles, so *.xml is simply not part of my development world.)
Deriving nouns: can be done either way, by reducing/eliminating BOM fields or by expansion, i.e. creating new objects mapped from the old ones. Both should be possible, so I'm thinking of something like XPath or JxPath, or CSS-style selectors.
Customizing templating: obviously, model changes shouldn't re-generate and overwrite changes you made to previously generated templates, so a merge algorithm should be used by the framework in updating templates (this may be the sledgehammer approach.)
Customizing verbs: obviously done in the same language as the verbs themselves. Again, either with merges or an AOP-style thing (not my preferred choice).
Once this is all done, continuations take the verb-noun operations and turn them into complete sentences.
The one thing I haven't mentioned so far is validation, and that's because this is a simple choice: it should be done in JavaScript. This is so that exactly the same logic is used server- and client-side, It also avoids extra code-generation, is DRY and can be changed in-flight, just like the above thee things.
Or not.
So, that is my idea. Not that complicated, intended to be incredibly powerful and very flexible. Why shouldn't I do it?
Firstly, there are already far too many frameworks out there. I should find a way of augmenting an existing structure, saving myself lots of time and contributing to something bigger than this in the process.
Secondly, creating a framework is a bad idea. I should know, I've already done it once or twice.
Thirdly, Java webapp developers such as I are not paid to work on frameworks, but on solutions. Therefore this should be done in my spare time, which introduces all kinds of issues when using it at work, for example.
In conclusion,the world would be a much better place if only everyone did what I said. the world of Java is not without hope in the latest mindshare battle. That said, any cool idea used in a Java framework would probably still end up easier to use and simpler in Ruby, by virtue of it being a nicer language.
Aargh.
So it's become increasingly evident to me that the the hour at which Ruby on Rails proceeds to stomp all over 80-90% of all Java webapp development is coming closer and closer, if it hasn't got here already.
As a developer, who's been online for ages and a computerphile for even longer, seeing whole fields of technology and millions of man-hours of work obsoleted in a period of months is something I've seen over and over again, so I knew it would inevitably happen to my own sub-sub-field.
And so, as a Java webapp developer, this necessarily requires a response, such as (for example) moving to RoR myself. I can do that if I have to, no problem, in fact I'd kinda look forward to it.
However, I'd like to make one thing clear: to anyone who claims that RoR can do things Java can't, I would politely request that they renew their acquaintance with the concept of the 'Universal Turing Machine', and then come back an re-examine those claims in the light of their newfound knowledge.
</snide>. Myself, I've also seen plenty of reaction from the world of Java, starting with things like Trails and Sails, and continuing with the various solutions that have been welded ontop of existing frameworks.
However, this is not enough to prevent Java's obsolescence in this field. All these solutions so far have been reactionary, and while it's good that the world of Java can readily admit influence from outside sources, all these solutions, by virtue of being copies or tributes to the original, cannot help but serve as a mere reflection of the power of the original.
(It's also worth noting that Python, Perl, Lisp etc. all had their Rails knock-offs months before Java did.)
Firstly, there are interesting ideas that don't exist in RoR. Of all of these, the most interesting by far is continuations.
Put simply, Spring Web Flow and Apache Beehive both encapsulate page-navigation workflow through the construction of state machines, similar in principle to directed state graphs, and influenced to a certain extent by JSF. [Web Flow does actually support continuations, I've just discovered.]
This is one way of expressing logic. However, logic is far better expressed in (guess what) a full-featured programming language, which will always be richer than any configuration file. This is what continuations should be used for. Construction of wizards, guides and sub-sequences could hardly be more natural.
Secondly, the (at least) two areas in which RoR is indisputably king is in inferring webapp structure from database structure, and in the all-important zero-turnaround time. Neither of these are impossible to do in Java, but I'll take them in turn.
Firstly, ActiveRecord. What is it that RoR does? Simply put, it makes the database the 'center of authority' (CoA) for the structure of the web-app. It infers what it can, which is usually 90% of what is needed, and lets the developer add the finishing touches.
Trails is similar in that it uses the business object model (BOM) as the CoA, and uses that to generate both the persistence (database) and the frontend webapp. This is in keeping with the Java view of keeping the semantic discussion at the object level instead of the DB level.
However, Trails also requires you do use annotations, which assumes that you have control over the source of your BOM, which in many cases isn't true (SOA-based methodologies can mean that you're simply the client of a different division, and that your BOM is generated from WSDL/XSD). This isn't a problem, Trails could just as easily use reflection to infer all the stuff that the tags point out to the framework.
Secondly, zero-turnaround time. Template-wise, Java already has this because JSP is recompiled when the source file changes. Personally however, I think JSP (1.x) sucks, and the whole idea of compiling markup templates into .class files is braindead, so I won't rely on this example too heavily, but nevertheless it proves my point.
WRT. zero-turnaround Java, in the traditional webapp this is of course not possible, but (a) this assumes that Java is your workaday language, whereas in fact it's entirely possible (and often desirable) for other languages such as Groovy, Rhino etc. to provide the meat of the application, for this very reason among others, and (b) you're not using something like Janino, which effectively provides the eval() function, and then some, to your normal JVM. (At a cost of course, but that's what facades are for.)
Yet another framework?
Which brings me to my point. If Java webapp development is not just to survive but also to thrive, reacting to RoR is not enough. It must also leapfrog RoR in the metrics by which RoR judges itself.
You can stop laughing now.
It's OK, I'll wait.
This in itself is fairly simple. So far people have been expressing web-development in lots of different languages, some (such as Ruby) more sympa than others (Java), but all of them, even JavaScript, when it comes down to it are not webapp-native languages.
For webapps, when it comes down to it, the language is very simple. There are four verbs: Create, Read, Update, Delete (CRUD). Your set of base nouns is defined by your database, or your object model, where-ever you put your authority. You derive nouns by operations on your base nouns. Each noun can have the four verbs applied to it.
This is all you need for webapps. The rest is reporting - list views, summary pages, query interfaces, etc. In an SOA environment these are simply other services, so that's easy for me, but I imagine other solutions would have to be found for this.
Thus the whole issue is resolved to three domain-specific problems: how to derive nouns, how to customise templating, and how to customise verbs.
(The typical Java response would be to have three different XML config files. Grr. Me, all my config files are generated via xDoclet and other fiddles, so *.xml is simply not part of my development world.)
Deriving nouns: can be done either way, by reducing/eliminating BOM fields or by expansion, i.e. creating new objects mapped from the old ones. Both should be possible, so I'm thinking of something like XPath or JxPath, or CSS-style selectors.
Customizing templating: obviously, model changes shouldn't re-generate and overwrite changes you made to previously generated templates, so a merge algorithm should be used by the framework in updating templates (this may be the sledgehammer approach.)
Customizing verbs: obviously done in the same language as the verbs themselves. Again, either with merges or an AOP-style thing (not my preferred choice).
Once this is all done, continuations take the verb-noun operations and turn them into complete sentences.
The one thing I haven't mentioned so far is validation, and that's because this is a simple choice: it should be done in JavaScript. This is so that exactly the same logic is used server- and client-side, It also avoids extra code-generation, is DRY and can be changed in-flight, just like the above thee things.
Or not.
So, that is my idea. Not that complicated, intended to be incredibly powerful and very flexible. Why shouldn't I do it?
Firstly, there are already far too many frameworks out there. I should find a way of augmenting an existing structure, saving myself lots of time and contributing to something bigger than this in the process.
Secondly, creating a framework is a bad idea. I should know, I've already done it once or twice.
Thirdly, Java webapp developers such as I are not paid to work on frameworks, but on solutions. Therefore this should be done in my spare time, which introduces all kinds of issues when using it at work, for example.
In conclusion,
Aargh.
2005/10/23
Another stupid IE bug: selectedIndex on IE6
Presupposing these functions:
This code retrieves a select by ID and adds an option to it. (The select is a single-value select.) The following code selects that option:
Or it would do, if it worked in IE. Apparently selectedIndex is readonly in IE4, which I don't care about. However, selectedIndex is also readonly in IE6, under certain circumstances, but it just fails silently. The workaround for the IE4 bug was as follows:
select.options[getOptionIdx(select, optVal)].selected = true;
This fails in IE6 with the stunningly unhelpful message "Could not set the selected property. Unspecified error."
HOWEVER, this code does work:
Removing the alert (or logging statement or whatever) gets you straight back to square one. Wierder still, surrounding [1] with a try-catch block will throw an "undefined" error, and set the select to the value, which I guess is the workaround I need.
Needless to say, I don't have this problem on FireFox. My completely uneducated guess is that DOM tree operations are slightly asynchronous, and that the time it took for the JS interpreter to move onto the next instruction was longer than the time it took for the DOM update thread to finish making changes, when computers were slower than they are now. I have no idea.
function addNewOption(select, value, label) {
var option = document.createElement("option");
option.setAttribute("value", value);
option.appendChild(document.createTextNode(label));
select.appendChild(option);
}
function getOptionIdx(select, value) {
if(!select.options) return -1;
for(var oNum = 0; oNum != select.options.length; oNum++) {
if(select.options[oNum].value == value) return oNum;
}
return -1;
}
Now watch carefully:var optVal = "1";
var select = $("exampleSelect"); //prototype shortcut
addNewOption(select, optVal, "one");
This code retrieves a select by ID and adds an option to it. (The select is a single-value select.) The following code selects that option:
select.selectedIndex = getOptionIdx(select, optVal);
Or it would do, if it worked in IE. Apparently selectedIndex is readonly in IE4, which I don't care about. However, selectedIndex is also readonly in IE6, under certain circumstances, but it just fails silently. The workaround for the IE4 bug was as follows:
select.options[getOptionIdx(select, optVal)].selected = true;
This fails in IE6 with the stunningly unhelpful message "Could not set the selected property. Unspecified error."
HOWEVER, this code does work:
var optIdx = getOptionIdx(select, optVal);
alert("optIdx="+optIdx);
select.options[optIdx].selected = true; // [1]
Removing the alert (or logging statement or whatever) gets you straight back to square one. Wierder still, surrounding [1] with a try-catch block will throw an "undefined" error, and set the select to the value, which I guess is the workaround I need.
Needless to say, I don't have this problem on FireFox. My completely uneducated guess is that DOM tree operations are slightly asynchronous, and that the time it took for the JS interpreter to move onto the next instruction was longer than the time it took for the DOM update thread to finish making changes, when computers were slower than they are now. I have no idea.
2005/10/16
In which I serve as a warning to others
- When assigning a value to the innerHTML property of any element that allows it on IE, if the string contains a <form> element, Microsoft IE6 throws an alert with "unknown runtime error".
- On Firefox, if you use a popup that makes callback to the window.opener and instantiates an XMLHttpRequest from within that callback, subsequent invocations of XMLHttpRequest fail with an internal exception. This has been a known issue since July 2004. The workaround for this is to have your callback function do setTimeout(0, "actualCallbackCode(/*args...*/)"), which (as I understand it) executes the callback within the original scriptContext instead of that of the popup's.
- Similarly, calls to window.open after having callback code executed in FF can fail with the same error message when the url is relative instead of absolute. The workaround for this is to compute an absolute URL from document.location.
- The IE team (much as I appreciate the hard work they do, etc.</diplomacy>) should scrap their scripting engine completely and use seamonkey's. The IE engine is old, crufty, nasty to debug in, and even when you have the (ancient) debugger installed(which also installs a different version of the scripting engine than that used by non-debugger-using users version of IE, making some bugs stupidly, braindeadeningly hard to pin down) tells you the line number of the error but not the file it occured in,and even gives you the relative line number of the error in the case of inline script, which is stupid.
Lessons learnt:
- I spent more time hunting for the FF bug (which was documented) than for the IE bug (which isn't). Yet because FF is OS, and IE is closed, IE is more annoying.
- innerHTML is like the easy path that leads to ruin, whereas true AJAX (i.e. with the response actually being XML and not JS or HTML fragments) is probably nicer and easier to work with yet harder to write in the first place.
- prototype.js is a wonderful library but only deals with responseText, never responseXML. This is something I would like to fix.
2005/08/14
Random links
Jason van Steenwyck on army logistics via armor plate. This is a place where some smart people put effort into saving lives. I wonder what business can learn from army logistics, and vice versa. It's all about the agility.
And again on the strategic importance of Haditha. This is exactly the type of 100% 24 Carat analysis that doesn't make it to TV.
Discussion on PC for the xBox's 'exception? what exception?' bug. Link ettiquete? This is new. (And regarding the timing of the leak, and it's effect on the share price: Steve, you're just too cool...)
Article from /. story above, which rests on the commoditization of the PC hardware business as providing apple a target against which to define itself.
And again on the strategic importance of Haditha. This is exactly the type of 100% 24 Carat analysis that doesn't make it to TV.
Discussion on PC for the xBox's 'exception? what exception?' bug. Link ettiquete? This is new. (And regarding the timing of the leak, and it's effect on the share price: Steve, you're just too cool...)
Article from /. story above, which rests on the commoditization of the PC hardware business as providing apple a target against which to define itself.
2005/08/13
How I see RoR changing the way we use, read & write software:
- Organic qualities of autonomy. Create a body then spend time on the brain. The body should evolved as the code grows. The brain is where firing a single neuron can tell the body to catch a ball, or make a face smile.
Each line of code in your brain that is not as important as this should be evolved into the body. - Minimizing the amount of code between the thought and the code that expresses the action resulting from that thought.
Metadata transfer standards & protocols:
The first step to a semantic web. RSS or RDF. Why is this important? Since the 'Net is a world of ideas, defining the substrate in which the expression of those ideas are rooted is important. This is why an RSS, RDF or Atom standards war would be a really, really bad thing. I don't refer to competing standards as a standards war. That's simple healthy competition. A standards war is two parties attempting to attain dominance in a standard space/market share.
If there is a war, and it gets ugly, then the resulting schisms in metadata comprehension will become the net's biggest headache, which would be a pity. Developers, you thought the browser wars were bad...
To put it mildly.
If there is a war, and it gets ugly, then the resulting schisms in metadata comprehension will become the net's biggest headache, which would be a pity. Developers, you thought the browser wars were bad...
To put it mildly.
An absolutely fantastic example of good security principles in action:
Documented as follows:
Why We Ask You to Re-enter Your Card Number
If you request delivery to a new address (one that you haven't used with us before with this credit or debit card) or want to send an e-mail gift certificate to a new e-mail address, we'll ask you to reconfirm the credit or debit card details.
That way, should some third party guess your password and try to order items using your account, their attempt will fail. We hope you understand that this is a valuable security precaution designed to protect our customers.
2005/07/29
Venting, notes:
- This sound is incredible.
- Leaking roofs in Belgium suck.
- After ranting about software patents for so long, I shamefully failed to post on our victory against the directive. Shame on me. My reaction was one of pure blissed-out thankfulness. Good things do happen in life.
- What is important is to love your job, use creative energy, in a cool team, and push yourself. I am there.
2005/06/18
2005/05/27
Belgium / followup
A friend once told me: "The most complex object is the user". This is true.
I just told this same friend, who shares my frustration with Belgian paperwork, and a somewhat militant attitude:
It's TRUE!
I just told this same friend, who shares my frustration with Belgian paperwork, and a somewhat militant attitude:
If you want to invade Belgium, you have to fill out form "Inv-10-A", and attach annexes confirming compliance with international law, acknowledgement of the ICC, prove that the soldiers (and their translators) are fairly divided between French and Flemmish speakers, and agree to start the process of an economic impact assesment report (and have it reviewed approved by an invasion steering committee), after which (assuming the report is approved) you must obtain permits for the use of heavy and armored vehicles in built-up areas, permission to break the speed of sound over populated areas, conduct background checks and psychological assesments on your soldiers in order that they may obtain weapons permits, and notify the police so they can help ensure that falling rockets don't hit civilians. Then your invasion can commence, but only for 38 hours a week, and no fighting may be done on bank holidays or weekends.
I'm sure I've missed some steps. Probably all the steps involving lawyers and accountants. Oh well...
It's TRUE!
Business processes:
Having seen a couple of approaches to codifying BP's I've formed the following opinions:
a) Less code is better. Business processes evolve. Software delivered in waterfall doesn't. In XP, adding features etc. sucks when your data model is shifting under your feet. (see also: why BP's should be expressed in (e.g.) a scripting language, not in compiled files.)
b) More freedom is better. People will ask "why can't I do X" where X is "attach an Excel file to the approved version of a final report, if the accountant signed the books in the last weekly meeting" - and coding that in Java or even a scripting language is stupid.
c) Less structure is better. Structure should be emergent, then inferred, not imposed. Evolved structure is seamless. Imposed structure is rigid and inflexible.
d) The more users, the better. Network effects increase an organizations net investment into a solution, and therefore (hopefully) increase its net benefit.
a) Less code is better. Business processes evolve. Software delivered in waterfall doesn't. In XP, adding features etc. sucks when your data model is shifting under your feet. (see also: why BP's should be expressed in (e.g.) a scripting language, not in compiled files.)
b) More freedom is better. People will ask "why can't I do X" where X is "attach an Excel file to the approved version of a final report, if the accountant signed the books in the last weekly meeting" - and coding that in Java or even a scripting language is stupid.
c) Less structure is better. Structure should be emergent, then inferred, not imposed. Evolved structure is seamless. Imposed structure is rigid and inflexible.
d) The more users, the better. Network effects increase an organizations net investment into a solution, and therefore (hopefully) increase its net benefit.
Subscribe to:
Posts (Atom)
