Monday, June 9, 2008

Hw vs Sw

Men and women, hawks and doves ...
Hw and Sw are like the ying and yang of the information revolution. Of course, all dualities hide a continuum and literally one cannot live without the other.
People think they understand hw (maybe they do), but I'm pretty sure they do not understand sw (I doubt I do either).
This entry tries to enumerate differences and synergies among both.


Sw predates Hw (in the sense of sw-running hw). Seems perplexing but it is true. It took some time to realize the minimal hw needed for sw to run on it. It is great that (finite) Turing-like hw is enough to run any computable sw.


Hw employs a minimal fragment of the people sw employs.
Hw produces a millionth of the different products sw produces.
Hw evolution has been consistently macro-predicted, the latest models of sw release take fixed points in time with no sure prediction of achieved functionality (but we get some).
Hw mistakes can destroy manufacturers. Sw mistakes have to be labeled as features.
A mistake in a hw piece requires its replacement. A mistake in a sw piece requires a patch write.
We have 2 centuries of experience with mass-produced goods, but only a few decades of sw quality evaluation.
A faulty Hw piece is easy to identify. A faulty Sw piece can take millions of people years to identify.
It is extremely expensive to produce 1 new piece of hw, a mass-market is needed. It is relatively inexpensive to produce a non-complex piece of sw, but it is extremely expensive to grow from it.
Hw duplication is expensive. Sw duplication is almost free.
Hw is Sw that has solidified too early. Sw is Hw that has not been fully debugged yet.
There is not such thing as a bug-free (non-trivial) sw.
Hw platforms change slowly. New sw platforms are developed every few years. (Understand platform as ecosystem, integration ...)
MS is a closed sw platform builder that owns an open hw platform. Apple is a closed hw platform builder that owns a (semi-)open sw platform. Linux is an open sw infrastructure to run sw on multiple hw platforms. (see open/closed, here open can be semi-open)
You can build Hw by componentization, duplication ... You can try to build sw by piling up stuff, but you usually just get a big mess.
Current Hw is no longer execution-predictable. Current sw no longer fits into one's head.
You cannot easily start again with a Hw architecture. You'd do better redesigning your sw architecture (and emulating the old one if needed).
The barriers to entry into Hw are colossal. A monkey with a PC could create good sw.
You can educate a Hw engineer predictably. Education alone cannot produce good Sw engineers.
A Hw engineer can plan his career. A Sw engineer considers himself lucky if he can plan his vacation.
When hw is badly done, only publicity can save you. When sw is badly done, you can get away with murder.
Good Hw guys usually were good mechanical tinkering children. Good Sw guys usually were insufferable philosophical kids.
Hw is provided as is but has full warranty. Sw is tailored to death, but has no warranty whatsoever.
Hw guys are to surgeons as Sw guys are to psychologists.

...

Saturday, June 7, 2008

Design Patterns

No blog about design can avoid mentioning GoF's book. It took the world by storm in the middle 90s and little by little it percolated to mainstream programming. After it there are JEE patterns, distributed patterns, enterprise patterns ... you name it.
Gof's comes from the Smalltalk tradition and shows how to add flexibility to class-based OO languages like C++ and Java. Gof's defines a common vocabulary and typical design solutions for some problems (based on the architectural work of Alexander). In this century critics have reacted to this, despising (with reason) those who use patterns like recipes (see Kerivesky's work for a reasonable alternative) and languages who need these patterns as "broken" (partly true). Newer languages based on the class-based OO tradition have tried to simplify or directly implement as idioms these patterns. Gof's is a book EVERY designer should read and understand, anyway.

I'll enumerate (with some notes) all Gof patterns (and some more here). I'll try to show some Scala implementation of these patterns as a personal exercise. UML 2 tries to simplify pattern representation (aiding to represent other high-level multiclass 'packages'). There is a nice (if slighty mocking) pseudo elements table relating them (worth printing to despise unknowing 'hackers').


Creational
These are patterns that try to simplify and generalize object creation strategies.
Singleton; Factory Method; Abstract Factory; Builder; Prototype

Structural
These help building common object structures.
Adapter; Decorator; Façade; Bridge; Composite; Flyweight; Proxy

Behavioral Patterns
These help building common collaboration patterns.
Chain of Responsibility; Visitor; Observer; Iterator; Mediator;State; Command; Mememto; Strategy

And, finally Gof includes a pseudojoke to help remember that no 'static' language is sacred and that scripting is usually needed: Interpreter.

Great book, (not the last word) but a common ground for OO developers.



Also check: JEE patterns, enterprise patterns, analysis patterns, ...

Davis' 201 principles of software development

This is a rewriting of Alan Davis' excellent 201 principles of sw dev list of principles. Some could be in several places (but I imposed myself to only show them once ...).
Some abilities can only be acquired by doing; Others will not be acquired early enough (if ever) unless good formal education is received early. Even others cannot be acquired (or only with too much effort) by some people.

Not all are valid now and you may not agree with all of them.

Outdated
CASE Tools Are Expensive (economically)
Be Optimistic About Hardware Evolution (current hw evolution requires mastery of concurrency).


Quality
Quality Is #1; Quality Is in the Eyes of the Beholder; Don't Try to Retrofit Quality; Productivity and Quality Are Inseparable; High-Quality Software Is Possible; Poor Reliability Is Worse Than Poor Efficiency
Comments
Avoid Broken windows; Avoid it works 'somehow'

People
Give Products to Customers Early; Communicate with Customers/Users; Align Incentives for Developer and Customer; Align Reputation With Organization; Follow the Lemmings With Care; Give Software Tools to Good Engineers;
Comments
Only those Doing can tell how, others can tell what.

Building (and Prototyping)
Grow Systems Incrementally; Change During Development Is Inevitable; If Possible, Buy Instead of Build; Build Software So That It Needs a Short Users' Manual; Every Complex Problem Has a Solution; Different Languages for Different Phases; Technique Before Tools; Use Tools, but Be Realistic; CASE Tools Are Expensive (in the process sense); "Know-When" Is as Important as Know-How; Stop When You Achieve Your Goal; Plan to Throw One Away; Build the Right Kind of Prototype; Build the Right Features into a Prototype; Build Throwaway Prototypes Quickly; The More Seen, the More Needed

Comments
If you PLAN to throw one away, you WILL throw two!



Documentation (and communication)
Record Your Assumptions; Use Documentation Standards; Every Document Needs a Glossary; Every Software Document Needs an Index; Use the Same Name for the Same Concept;
Comments
If you plan to document late you won't, or worse; Unsynch'ed docs are worse than no docs (except for saving face);
If you cannot do docs you are NOT a good developer: CANNOT deal with multiple languages, NO abstraction capability; NO design; CANNOT communicate


Education
Know Formal Methods; Don't Ignore Technology; Research-Then-Transfer Doesn't Work; Take Responsibility
Comments
If you are not educated, you will AT BEST reinvent all wheels


Requirements
Poor Requirements Yield Poor Cost Estimates; Determine the Problem Before Writing Requirements; Determine the Requirements Now; Fix Requirements Specification Errors Now; Prototypes Reduce Risk in Selecting User Interfaces; Record Why Requirements Were Included; Identify Subsets; Review the Requirements; Avoid Design in Requirements; Use the Right Techniques; Use Multiple Views of Requirements; Organize Requirements Sensibly; Prioritize Requirements; Write Concisely; Separately Number Every Requirement; Reduce Ambiguity in Requirements; Augment, Never Replace, Natural Language ; Write Natural Language Before a More Formal Model; Keep the Requirements Specification Readable; Specify Reliability Specifically; Specify When Environment Violates "Acceptable" Behavior; Self-Destruct TBDs; Store Requirements in a Database
Comments
Do not do GUI without fast prototyping tools, else stay with TUI! (No tools, no GUI)
Whys and assumptions provide metaknowledge

Design
Transition from Requirements to Design Is Not Easy; Trace Design to Requirements; Evaluate Alternatives; Design Without Documentation Is Not Design; Encapsulate; Don't Reinvent the Wheel; Keep It Simple; Avoid Numerous Special Cases; Minimize Intellectual Distance; Keep Design Under Intellectual Control; Maintain Conceptual Integrity; Conceptual Errors Are More Significant Than Syntactic Errors; Use Coupling and Cohesion; Design for Change; Design for Maintenance; Design for Errors; Build Generality into Software; Build Flexibility into Software; Use Efficient Algorithms; Module Specifications Provide All the Information the User Needs and Nothing More; Design Is Multidimensional; Great Designs Come from Great Designers; Know Your Application; You Can Reuse Without a Big Investment; "Garbage In, Garbage oUt" Is Incorrect; Software Reliability Can Be Achieved Through Redundancy



Comments
"Garbage In, Garbage oUt" Is Incorrect (?): design garbage rejection (checks, PbC ...) The world is a mess, build a garden.
Do not outclever yourself; Be humble (but ask for a raise!)
Transition from Requirements to Design Is Not Easy : The whole industry is taking more than 20 years to learn this: OO, XP, Agile, Declarative, Iterative, Incremental ... But then it goes against the pay structure ... So real designers disappear
No evaluation of alternatives means a lemming is following a script
KISS: If we wanted complex, we would be doing it like always (without sw help)
Design for change: YAGNI, for you ...
Build Generality into Software: grow it!
Use Efficient Algorithms: Oh, but I would need education for that ...
The interface (in all senses) is the sw (to non-builders)

Coding
Avoid Tricks; Avoid Global Variables; Write to Read Top-Down; Avoid Side-Effects; Use Meaningful Names (for meaningful stuff); Write Programs for People First; Use Optimal Data Structures; Get It Right Before You Make It Faster; Comment Before You Finalize Your Code; Document Before You Start Coding; Hand-Execute Every Component; Inspect Code; You Can Use Unstructured Languages; Structured Code Is Not Necessarily Good Code; Don't Nest Too Deep; Use Appropriate Languages; Programming Language Is Not an Excuse; Language Knowledge Is Not So Important; Format Your Programs; Don't Code Too Soon


Comments
Write Programs for People First: This is the most important principle for coders (but choose your readers !)
Use Optimal Data Structures: requires education
Get It Right Before You Make It Faster: premature optimization
You Can Use Unstructured Languages: or untyped, or hacked (just be knowledgeable of the trade offs)
Don't Code Too Soon: true, but (for sweatshops) neither too late!
Removing lines of code is Good.


Testing
Trace Tests to Requirements; Plan Tests Long Before It Is Time to Test; Don't Test Your Own Software; Don't Write Your Own Test Plans; Testing Exposes Presence of Flaws; Though Copious Errors Guarantee Worthlessness, Zero Errors Says Nothing About the Value of Software; A Successful Test Finds an Error; Half the Errors Found in 15 Percent of Modules; Use Black-Box and White-Box Testing; A Test Case Includes Expected Results; Test Invalid Inputs; Always Stress Test; The Big Bang Theory Does Not Apply; Use McCabe Complexity Measure; Use Effective Test Completion Measures; Achieve Effective Test Coverage; Don't Integrate Before Unit Testing; Instrument Your Software; Analyze Causes for Errors; Don't Take Errors Personally

Comments
Nowadays, no unit testing means component coding is unfinished
Untested sw is worth less than zero: some people get away with making users the testers ...
You only learn from mistakes (if you ever learn).


Management
Good Management Is More Important Than Good Technology; Use Appropriate Solutions; Don't Believe Everything You Read; Understand the Customers' Priorities; People Are the Key to Success; A Few Good People Are Better Than Many Less Skilled; Listen to Your People; Trust Your People; Expect Excellence (and be a model); Communication Skills Are Essential; Carry the Water; People Are Motivated by Different Things; Keep the Office Quiet; People and Time Are Not Interchangeable; There Are Huge Differences Among Software Engineers; You Can Optimize Whatever You Want; Collect Data Unobtrusively; Cost Per Line of Code Is Not Useful; There Is No Perfect Way to Measure Productivity; Tailor Cost Estimation Methods ; Don't Set Unrealistic Deadlines; Avoid the Impossible; Know Before You Count; Collect Productivity Data; Don't Forget Team Productivity ; LOC/PM Independent of Language; Believe the Schedule; A Precision-Crafted Cost Estimate Is Not Foolproof; Reassess Schedules Regularly; Minor Underestimates Are Not Always Bad; Allocate Appropriate Resources; Plan a Project in Detail; Keep Your Plan Up-to-Date; Avoid Standing Waves; Know the Top 10 Risks; Understand Risks Up Front; Use an Appropriate Process Model; The Method Won't Save You; No Secrets for Miraculous Productivity Increases; Know What Progress Means; Manage by Variance; Don't Overstrain Your Hardware; Be Pessimistic About Software Evolution; The Thought That Disaster Is Impossible Often Leads to Disaster; Do a Project Postmortem

Comments
Don't Believe Everything You Read: This is the most important principle for managers
People trumps process, technology and rules
Use Appropriate Solutions: use proportional force
There Are Huge Differences Among Software Engineers: but it is in the interest of many (bad ones, the paying structure, friends) to hide this; but please, at least, remove the negative producers.
You Can Optimize Whatever You Want: but optimizing something may mean not optimizing something else.
Collect Data Unobtrusively: do not try to turn everybody into bean counters.
Cost Per Line of Code Is Not Useful: If you do not agree, then YOU are not useful.
Don't Set Unrealistic Deadlines: they are not deadlines, they are just ignored (maybe silently).
Know Before You Count: apples and oranges may not add up.
Nothing is foolproof: fools are the most intelligent agents of entropy in the Universe.
Be Pessimistic About Evolution: (surprise) entropy wins in the end.
The Method Won't Save You: Only people save (amen).
Manage by Variance: be a change detector and presenter.
(non natural) Disaster: requires multiple failures in a chain: if it happens, MANY things where done wrong. Some people really believe things sort out by themselves!


Product Assurance
Product Assurance Is Not a Luxury; Establish SCM Procedures Early; Adapt SCM to Software Process; Organize SCM to Be Independent of Project
Management; Rotate People Through Product Assurance; Give Every Intermediate Product a Name and Version; Control Baselines; Save Everything; Keep Track of Every Change; Don't Bypass Change Control; Rank and Schedule Change Requests; Use Validation and Verification (V&V) on Large
Developments


Evolution
Software Will Continue to Change; Software's Entropy Increases; If It Ain't Broke, Don't Fix It; Fix Problems, Not Symptoms; Change Requirements First; Prerelease Errors Yield Postrelease Errors; The Older a Program, the More Difficult It Is to Maintain; Language Affects Maintainability; Sometimes It Is Better to Start Over; Renovate the Worst First; Maintenance Causes More Errors Than Development; Regression Test After Every Change; Belief That a Change Is Easy Makes It Likely It Will Be Made Incorrectly; Structuring Unstructured Code Does Not Necessarily
Improve It; Use Profiler Before Optimizing; Conserve Familiarity; The System's Existence Promotes Evolution

Comments
Software rots (we have not much self-modifying sw and the world keeps changing).
Language (use) Affects Maintainability: repeat until death! Beware of fashion.
Sometimes It Is Better to Start Over: Sometimes It would have been Better to Start Over
Renovate the Worst First: Low hanging fruit tastes great!
Belief That a Change Is Easy Makes It Likely It Will Be Made Incorrectly: this can only be learned by mistake :)
The System's Existence Promotes Evolution: Real sw engineers are social engineeers (of a sort).

Saturday, May 31, 2008

Design Principles Notes

This notes gather guidance and principles of software design (OO design in particular).
This is a work in progress.
It is hard to create a perfect structure of orthogonal principles as some relate to each other.
Links:
wikipedia
Good: http://www.cmcrossroads.com/bradapp/docs
A Java study: http://javaboutique.internet.com/Case_Study/
Some principles expained: http://www.cs.sjsu.edu/faculty/pearce/cs251b/principles


0. Serenity Principle (SP?): Separate what can change from that that cannot.
God, give us grace to accept with serenity the things that cannot be changed, courage to change the things that should be changed, and the wisdom to distinguish the one from the other.
Common Closure Principle (CCP) Classes that change together must be placed in the same package.
See: Policy and mechanism


1. Liskov Substitution Principle (LSP): All uses of A can be substituted by A' (A' subtype of A).
All base class usages (use define nature, interface) can be substituted by derived classes without external behavior change.
Guides proper inheritance usage. Inheritance should be additive, never restrictive.
If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.
When extending: Preconditions cannot be straightened, Postconditions cannot be loosened, visible Invariants cannot be changed (?). Invariants: users depend on this both before and after sending a message.
Use a proper set-based inheritance relationship. Not following set semantics is very risky.
Subsumption Rule: A reference to a subtype can be used in any context where a reference to a super type is expected.
This principle extremely limits what SHOULD be done with the pure extension (inheritance) mechanism. Do not follow at your own risk.
Squares aren't Rectangles!
See: http://www.cs.sjsu.edu/faculty/pearce/cs251b/principles/liskov2.htm



2. Dependency Inversion Principle (DIP): Abstractions should not depend upon details. Details should depend upon abstractions.
High-level modules should not depend upon low-level modules. Both should depend upon abstractions.
Depend on abstractions, not implementations.
Program to an interface, not to an implementation. Separate interface from concrete implementations. Depend upon abstractions. Decouple helpers with interfaces.
Do not make high-level (general) classes directly dependent on the implementation of lower-level ones (its helpers).
Abstractions(core client visible, testable, components) should not depend upon details (helpers). Details(helpers) should depend upon abstractions (interfaces): this is the "inversion" , the helper depends upon a new abstraction, and the abstraction no longer depends on the helper directly.
High level or low level modules should not depend upon each other, instead they should depend upon abstractions.
Frees you from having to implement in either a down-top (always runnable and useful) approach or a top-down approach (whole view, structured, progressive refinement) with mock implementations. You are free to decide you implementation strategy guided by: risks, weights, scenarios, ... allows TDD and others.
Allows you to use compositional techniques for program creation: components.
Allows you to test each element in isolation (unit tests) as well as a group of them (functional and scenario tests).
Program to an interface not to an implementation. Corollary: Do not access/modify directly the internal state of a client.
If you depend on a concrete client, you will probably end up depending also on the concrete clients of the client, ad nauseum.
Reify design in code (by not tying yourself to an concrete "future" implementation).
Minimize concrete implementation dependencies.
Note that interfaces in Java are clean but a bit unwieldy and underpowered (see traits in Scala). Requires more concepts.
The Inverted Tree: shown core modules down and and future usage layers on top of it. Inversion: Client (user) code invokes base code. This is the basis of frameworks, independent of implementation technique. Inversion appears when older code will call newer, more refined one (call-backs).
Reify structure and dependencies.
Related: see Facade, Interface, TDD, component, composition, IoC, DI, framework, Spring, Guice
See:
Protocol Stack Example: http://www.eventhelix.com/RealtimeMantra/Object_Oriented/dependency_inversion_principle.htm


3. Open/Closed Principle (OCP): modules should be open for extension, but closed for modification.
Modification can easily break the design of a piece of sw.
Modification requires deep internal knowledge.
Solving a family of problems instead of the concrete one you have to face.This can conflict with YAGNI.
You need to modify if the current design cannot accommodate your extension/use easily.
Embed design decisions and restrictions in the source code (final, protected).

Open/Closed object
Dynamic Dispatch Rule: Objects should decide how to handle the messages they receive.


Open/Closed class
It should be possible to change the implementation of an object without modifying its class.
It should be possible to change the internals of a class without needing to even recompile its clients.
Abstraction Principle: The interface of a module should be independent of its implementation

See: Strategy, State, and Bridge Patterns


Open closed system
Service-Oriented Architecture (SOA) is an Open/Closed architecture for systems.
Reflective systems allow the system to dynamically discover the interfaces implemented by third party components. Each component is expected to implement a meta-interface that describes the application-specific interfaces that it implements.
Separate policy (max change) from mechanism (stable).

Open/Closed principle in HCI:
The most open sw artifact is a language or other building-blocks based solution.
The better closed a sw piece, the easier it is to experiment with it without risk.
Good GUI design uses the Open/Closed principle to guide and present the possible transitions in an intuitive way, without forcing analytical thought: see flow.


4. Design by contract and responsibilities (DBC and RDD)
It is a series of techniques for OOD: guiding the distribution of functionality and its definition and evolution.
DbC involves: preconditions, postconditions, invariants. You get: well-defined interfaces, closed designs (see Open/Closed) easily extensible, a basis for some types of testing, the capacity to fail fast, a way to warrant consistency.
Responsibility Design involves: Objects, responsibilities and collaborations. You get well-decoupled, highly cohesive and easily comprehended classes, well-defined associations and a balanced overall class design.
High Cohesion by responsibilities - Low Coupling by good delegation and concept reification.
See: OOSC for DbC, DOOS for responsibilities


5. Composite Reuse Principle (CRP)
Favor composition over inheritance to achieve polymorphism.
Favor delegation over inheritance. Delegation can be seen as a reuse mechanism at the object level, while inheritance is a reuse mechanism at the class level.
Implementation inheritance is the goto of OOP.
Favor composition over inheritance.
When in doubt, do not inherit.
See: Strategy pattern


6. Modularity Principle (MP): High cohesion and low coupling
Modularity Principle tells us that modules should be cohesive and loosely coupled.
The Facade pattern can lower the coupling degree between modules.
The Mediator pattern can reduce the dependencies between the members of a package.
The members of a subpackage can be considered to be members of the super package (transparent packages) or not (opaque packages, like in Java.)

Acyclic Dependency Principle(ADP): Avoid cycles in the package-level dependency graph
It is sometimes difficult (impossible) to avoid cycles in the class-level dependency graph. But reject packages with cycles!
Interface Segregation Principle (ISP): Many specific interfaces are better than a single, general interface
Release Reuse Equivalency Principle (REP) The granule of release is the granule of reuse.
Common Reuse Principle (CReP) The classes in a package are reused together. If one of the classes in a package is reused, all the classes in that package are reused.
Stable Dependencies Principle (SDP) The dependencies between packages must always be in the direction of stability. Less stable packages should depend on more stable packages.
Stable Abstraction Principle (SAP) The stable packages must be abstract packages. The instable packages should contain the concrete implementations.

Note: Java modularity is incomplete. Both NB & Eclipse add higher abstraction 'packages' (see OSGi)


7. Law of Demeter (LoD) or Principle of Least Knowledge (PLK): Only talk to your friends
A method should only send messages to itself, its parameters, objects it creates (in the method), global objects (of the object/class), and objects it contains (inner of the method or of the object).
Law of Demeter for Functions/Methods (LoD-F): Object A can request a service (call a method) of an object instance B, but object A cannot “reach through” object B to access yet another object to request its services.
A method M of an object O may only invoke the methods of the following kinds of objects:
- O itself
- M's parameters
- any objects created/instantiated within M
- O's direct component objects

Objects are less dependent on the internal structure of other objects, object containers can be changed without reworking their callers.
Use only one dot (approx).
Delegation is an effective technique to avoid Law of Demeter violations, but only for behavior, not for attributes.
Law of Demeter can degrade performance:
Demeter Transmogrifiers: requires writing a large number of small “wrapper” methods to propagate method calls to the components. A class’s interface can become bulky as it hosts methods for contained classes resulting in a class without a cohesive interface.

Law of Demeter for Concerns (LoDC): Only talk to your friends who share your concerns, requires aspects (or traits).

Designing for extension: (frameworks)
Strong Adherence to LoD may be required for reusable class frameworks (usable by client subclasses as well as "normal" clients). Some of the rules they propose are:
- Whenever an object needs to request a service of some other external object, this external service request should be encapsulated in an internal non-public method of the object. This allows derived classes to override the service request with a more specialized one (it is also a use of the GoF Template pattern).
- Whenever an object needs to instantiate some other externally associated object, it should do so using a non-public method to perform the instantiation. This allows derived classes to instantiate a more specialized object if needed.


9. End to End Argument (EEA)
It should be possible to defer work as late as possible (YAGNI)
Avoid intermediate steps.
Lazy evaluation is the general case!
The best optimization is done when all possible affected information is available
See: JIT



OO Tips

Naïve OOAD:
Start with the domain, language analysis helps:
names -> domain objects
adjectives -> derived classes
verbs -> methods
patterns, structure -> design objects

Polymorphism:
- Subsumption Rule: A reference to a subtype can be used in any context where a reference to a super type is expected. (LSP)
- Dynamic Dispatch Rule: Objects decide how to handle the messages they receive.

Divide an app into 1 core and N helper reusable frameworks
Favor immutability for small objects (over get-set beans).
Model classes with complex behavior as state machines
Choose the most restrictive access possible. You will not be able to close it up when there are users.
Structured Programming smells:
- Control-Driven Solutions (switch, case, if, instanceof) point to structured programming, Data-driven solutions are more OO.
- Dynamic checking should be subsumed in the design of the application (avoid instanceof).
- Control modules that hold the logic of multiple components. Control and algorithms are distributed in OO !
Incomplete delegation smells:
- big classes: split into helpers
- multiple get-set: clone, update operations

Sunday, May 11, 2008

Some design koans

A good design is worth ten implementations.
A bad architecture can´t be saved by a million developers (in the long run).
Software rots.
Software flexibility comes from the blood of its creators.
Design patterns in a language/framework are code idioms in a better one.
Refactoring is trying to get design out of entropy-full code.
Sw process is how it is done, not what is written or talked about.
You get farther striving for simplicity than for cleverness or features.
Design is what can be said about software without having to read each line of code. The more that needs to be said the worse the design.
Reuse is a dream, but we are allowed to dream. Aren´t we?
Reuse is now at the copy-and-paste level.
Software reuse is what a developer has learned after completing a project.
A software factory is an oxymoron.
Good code can only be appreciated by developers, the effects of bad code are detected by anyone.
Abstraction is the last refuge of the reckless.
As in real life, good looks can hide mean souls.

Those are mine (as far as I know), there are great sw koan writers around, I´ll add links latter.

Thursday, May 1, 2008

About roaches & Java: Climbing with grace (with Scala!)

There is some tension around about Java: what is the Next Big Thing(tm)?, is Java mature?  Is Java dead? .... The fact is, as has been said elsewhere, that Java has reached cockroach status: meaning there is no way back. So Java is now on par with Cobol, Fortran and C: code (and work) is not going away! Also Java has set the bar higher than any other roach before it: 
- Cobol: legibility, closeness to user model
- Fortran: numerical and algorithmic expressiveness
- C: portability, simplicity, closeness to underlying  model, speed
- Java: garbage collection, objects, dynamic loading, virtual machine, language interoperability, APIs, IDE ...
For a future aspiring roach it has to at least be able to have the characteristics of all previous roaches. (When I say Java of course you can put .Net if you are living in that closed world).
It seems the dev world is, at last, ready for FP (wether newcomers are ready for it is another question. But newcomers are forced to do what they have to do). And of all the proposed New Things it seems Scala is the thing that retains most good Java things and adds most good "new" things.
What Scala has got now:
1. Exceptional Java interoperability
2. Great (for a non pure FP) functional constructs
3. Better OO than Java (traits, companion objects)
4. Nice core community (and I mean nice, being nice to newcomers and to other players is a must some Gollums have learned the hard way ...)
5. Academic soundness 

What Scala is missing right now (to be on a par with what Java has got):
1. Good tutorial: there is a book in the works that may be of the right level for Java developers. There are a bunch of scattered blog entries around. Missing: use cases and idioms, more Java frameworks-Scala samples
2. API stability and development: more Java helpers-wrappers, better documentation.
3. Killer applications?: Java, and the JVM, is the "killer application" of Scala.  
4. Patronage: Academia is behind Scala but some further industry support is needed. Plugins for main IDEs are on the way, but Scala is a more complex language to support that others.
5. Clearer roadmaps: Although stability is settling up lately, the only way to know where we are heading in the next moths is to check the bug
6. Better visibility: There is a need for more "in the wild" tools, programs, frameworks, applications, API. And this is where most of us should be working on. Start using Scala for some small projects now !

Tuesday, April 8, 2008

My Adventure Heroes


They say you can learn a lot about somebody by knowing who their heroes are. Of course, it seems cool to say you have no heroes, but, deeply, having no models means something quite uncool ...
This is a list of people whose work in adventure games I admire. I may add more people and more info about them in the future.


Tim Schafer
Just the best of them all, showing how you can evolve the genre without diluting it. Sadly, when he was starting to show the world what he is capable of, Lucas Adventures folded.

Brian Moriarti
From Infocom, through Lucas creating a wonderful and still not surpassed mythic tale with Loom. His career is just awesome.

Ron Gilbert
The guy behind SCUMM (with Aric?), Maniac Mansion, The Secret of Monkey Island. Licensed SCUMM to create Adventures for children. He has been "underground" for some time, it seems that he is coming back to mainstream.

Jane Jensen
The best writer-creator of computer games. The creator of the best series: GK. Each game is a model in a style of game. Has a couple of good mainstream novels. Next year, a new series will start!

Rafael Latiegui
From Igor to world-wide success with Runaway. A model career in gaming, never compromising his principles. Though his games are well-known he is not.

Hall of Shame of Adventure:
Doom's copycats: They are in the hundreds ...


Lucas*rts: The Empire Stroke Back, who cares? The Jedis are Returning!

These days I took a look around the Monkey related sites ... I read what the corporate entity said about a Monkey sequel (something like by 2018 we will think about it) and it is not only mean and ruthless but self-damaging. To the little tool who said that: I do not know where I'll be by then (if I'm alive, I´ll be breathing adventure), but I´m pretty sure that you won´t be around LucasArts or LucasArts will be no more ... Adventure may or may not suit your tastes but it is the most creative, deep inmersion (deep as in emotional as opossed to "Sith" -reptile mechanic - hand eye coordination) genre computers have given us (yes, I could not pass level 54 in commandos joyturd!).

Gone are the days when everybody and their dog said the Adventure genre was dead. It is peculiar that those days predate the IT is dead .com crash by a few ´millenium bug´months but that´s another story ... or is it? There is much to be written about sw as a business (a ship full of captain pirates in a shark infested archipielago. Where is Guybrush when you need him?). I had the perfect timing to finish U in the crash, but that is another story indeed!

The history of Luke-Lucas and the seeds of SW (not to be confused with software) are now part of folklore. It seems now clear that not much originality can come out of Lucas*rts, be it in the adventure genre or elsewhere. It seems now clear that the creative sparks that had to leave in the crisis are returning. With "Luke" the question is: is Empire Strikes Back a self-fullfilling prophecy? Has not George "Lucas" Skywalker become the one he feared most: Darth "Corporate Tool" Vader ? 

At least Sam and Max escaped alive ... Tim´s new game is clearly Tim´s view of what LucasArts killed (adapted to these no-thinking 3rd generation console years surface and I think the game will be full of deep, creative irony). An older, now lost, Lucasfilm(tm?) would have created Ron´s version of Pirates of the Caribbean years before Disney´s did. I´m afraid we make be shocked this summer to see Indy dying a long sad death too ... Indy´s adventure has been postponed.

It is clearly not the same "Luke" that fought for creative control of his brainchild the one that killed the brainchildren of other Jedis. At least, he let Pixar be ... What has this "Luke" seen in the cave? Well, the Jedis are returning ! 


Monday, April 7, 2008

Inform 7 (or a NL DSP for IF !)

DISCLAIMER: This is going to be perceived as a critic of I7 (it is in part), because it is something NEW and DIFFERENT, which is quite GOOD so: I find I7 EXTREMELY interesting and a joy to experiment with (it´s been more than a decade since I were involved in IF and I´m coming back just because of I7). Also, I´m probably going to contradict myself multiple times ... I may even agree with what I write :) I only dissect things I really like, what I do not, I just ignore ;) .

This post is based on a discussion on rec.arts.interactive-fiction in March 08 about some writers choosing TADS instead of Inform 7 for a course.

  •  I find the whole IF (including Graphic Adv) to be conceptually OO to the core. What attracted me to it was all the model/simulation aspects of it (in the broadest sense possible ...). 
  •  I do not think an IF writer (vs modeler or developer or library creator) must be interested in the internal mechanisms by which his definitions get finally executed in minute detail.

I find Inform to be a lot more difficult to explain than other, less tied systems, like advsys (to put a lispy-oo example). Likewise, internally SCUMMVM is surely much more complex than Wintermute ... To grok Inform you may have to grok VMs, partially the historical development of ZIP, Inform 6, how Inform 7 notation gets translated into I6 (law of leaky abstractions of sw).


  •  I detect a (partial) rejection of I7 based on its GUI ( writers are used to simpler editors or word processors, idea processors or even script tools) and pure text is their core competency. It is even fashionable to consider TUIs as superior (just more expressive in exchange for being more opaque). It takes time to master an IDE, but it is not worth the fuss for just a few weeks of use. The UI is the SW.
  •  Another dissonance may be with presenting a uniform pseudo NL for all parts of the work. I think some writers may feel I7 syntax is a bit of a transvestite ... It is hard to modularize rule sets without experience, guidance. With a pure OO model you just look for responsibilities (responsible object).

Most of us devs, can look at I7 source for rules and mentally translate to Horn clauses or whatever formalism suits us best, but probably a writer with no formal training on math cannot. And some may be getting the message: hey you are not good at your core competency. I do not find the current form of rules in I7 (I'm just starting using them) to be the best representation. I find the NL approach to describe the object relations, static structure, containtment hierachies ... superb.

  • Procedural code/stateful programming is EASY to grasp, specially if given in small doses (just the part of the algorithm I am concerned about, the one that this method of this object has to deal with ...). Flags and simple vars have always been part of (almost) any IF tool.
  • Otoh, Event programming (concurrency too) is hard to grasp, and most notations/practices suck for this (actors being one of the best, and actors are OO to the core). A simple REPL loop is easy to master (user input-system response) but when you have cascading triggers and reactions: not well modularized rules are hard, even objects without scenarios/collaborations are hard, but you can always fall back on to an object structure/class inheritance tree with responsibilities. Multiple hooks require you to know the whole algorithm the framework follows to some depth (hiding the alg does not help at all). We are very bad at following the execution path so rule systems seem to
  • Declarative prog is harder to grasp: you have to be a good modeler, you have to be good with complex logical expressions and transformations and you have to be able to relinquish control (when, where, how is this exactly going to be fired, executed or even implemented, have I covered all cases? ....). Hell (sorry), the whole "professional" sw scenario is an example of letting declarative prog enter little by little (from configuration, to containers, to business rules, to object creation, to initialization of complex structures...). Anyone with enough experience developing knows that more declarative code is the way to go but it takes a lot of time to accept/embrace it, at least to those with a deep procedural background (most?) ...

I7 is still too new, there seems to be missing yet good examples and collective experience in it strong points and faults. I sense leaky abstractions there ...

But choosing is fearsome specially if you do not have enough experience to evaluate and I7 seems to make a point of being minimal (less in the core, more libraries) and letting you choose more. This is GOOD for flexibility but to beginners it can be bane ! Too much can also be daunting (but I have no experience with TADS libraries) The JDK is a monster but beginners love they have it there and can selectively pick up things (they usually implement things that are there already or search for things so particular that really have no place in a SDK .... but sometimes they are there too!).


I7 strings or formatting/printing facilities are a bit cumbersome (all that you cannot write ", ...) and maybe underpowered. Why not use escapes and references? Strings should be one of the most powerful abstractions in an IF language. This surprises me as I though Graham would have done this (I had him for a quite perly guy). Even the NL references (pronouns) I feel are underpowered (cumbersome).

Also, in i7, not having some sort of mixins, traits, multiple inheritance, interfaces or the like makes a OO implementation conceptually crippled (though simpler typewise). Not that you cannot find a way to simulate-implement this but this should be at the language level (perhaps in I8?).

  • You usually start implementing (your firsts) IF works by creating objects (definitions, declarations, rows, structures) and then adding (code) snippets for special functionality. IF presents a TUI that consists of "verb with objects" commands, and rather than create some sort of cascading switch in verbs (the easy route) you'd rather put code in the objects. This is object based "prototype" programming.

Rules, as has been said (Plotkin even has shown it can be rules all to the bottom), are more flexible and can go from the "use level" (global switches) to the minimal and most specific event in the most special situation but you are forcing me to think ahead (and not about what I naively may think is the important part). By the way (sorry we all OO heads have to say this), rules are objects too ...

Even the IF practice shows it is easier to exchange objects behind the scenes than to transform them radically. (Non) likewise it is many times simpler/safer to copy and modify than to refer to the same shared data ... It is safer to always declare functions and internally use whatever is best (constants, variables).

In the end I think this boils down to: It is easier to objectify than to abstract. It can be objects all the way down, rules all the way down or in between (probably the best but you are forcing me to think ...) ... give me patterns, give me guidance, give me the ten testaments, when I do not need them I´ll break them, don´t worry ...

PD: Inform is in better shape than ever, the GUI is an ELEGANT piece of sw, I feel I will not need to delve deep into the generated files or I6 except in very special cases and it may be a good  declarative frontend (perhaps with a little bit more of punctuation or structure) to other backends, VMs ...

Thursday, February 14, 2008

Sw: Craft, Engineering or Science?


Sofware is part Maths, part Engineering and part Craft. Remove any of the parts and you have a mockery, so all the 3 ingredients are essential. If you remove maths: you cannot deal with types, compilers, complexity, algorithms ... If you remove Engineering: you miss teams, planning, standards, quality, time, cost and risk analysis, design ... If you remove craft you are condemned to repeat the same solutions for any problem because the only way to learn to do sw is by doing it (know-how).



Modern curricula try to specialize people in giving more weight to one of the components. When is a person ready to specialize is a personal issue. Some people are great with abstraction and cannot deal with real life details, other people work better alone and are extremely creative, while others are great at communication, dealing with people, coaching and coordinating. But, independent of your strong points, if you cannot deal acceptably in the three areas you will not be a good sw person. Not that you cannot do great things, but extreme specialization is for insects!

Tuesday, February 12, 2008

Using LDAP SDK on OS X with NetBeans

As an example of integrating an external jar for use with NB in java projects ... Probably it is better to stick with what is provided by JNDI, it is much better now, but if you have a project that uses ldapsdk.jar: 

  • Download  ldapsdk_java_20020819.zip from http://www.mozilla.org/directory/javasdk.html
  • Unzip it, there is a buildjsdk.txt that hints about the next steps
  • cd to mozilla/directory/java-sdk
  • execute make -f ldap.mk JAVA_VERSION=1.4 to get .class files (optional)
  • execute make -f ldap.mk basepackage to make the ldapsdk.jar (optional, previous command required: 301968 vs 301913 bytes in the jar I "inherited")
  • execute make -f ldap.mk doc JAVA_VERSION=1.4 (to generate javadoc)
To successfully execute the previous commands you may need to:
edit ldap.mk : add -source 1.4 -target 1.4 to each JAVAC variable definition like:
JAVAC=$(JDKBIN)javac -g -classpath "$(JAVACLASSPATH)" -source 1.4 -target 1.4
---
JAVAC=$(JDKBIN)javac -g -classpath "$(JAVACLASSPATH)"

create some environment vars: export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Home
All this mess  is needed because the sdk uses enum as an identifier, and Java 5 uses enum for the typesafe enumeration pattern, as a reserved word. You need to either change the source code or compile for Java 1.4 ... So much for Java's backward compatibility. Still, you may get some deprecation warnings ...
  • Open NB (5.5.1): Tools -> Library Manager
  • Create a new library
  • add ldapjdk.jar to Classpath
  • add ./mozilla/directory/java-sdk to Sources
  • add ./doc to Javadoc
Add to your project the library you just created (and maybe remove the previous jar). You may need to restart Netbeans (to reload the classpath).
Test: 
  • Try MR-> Go to Source
  • Put breakpoints 
  • Use the "." for contextual javadoc, code completion ...


I hope my next NB entry will be about a detailed installation of Scala support in NetBeans (see Caoyuan's fine work)


A Beginning Is A Very Delicate Time

A good prologue is a must ... Before LOTR´s we had Dune´s
Lately, I've found myself trying to post comments to too many blog entries. Comments that will be dispersed around, not much interesting to anybody but me. So I'd rather write my own comments all on the same place. 
Entries are not supposed to be closed ever, so this is not a 'publication' ...