Title: "Senior Computer Engineer" (methodologist / SoftwareArchitect
/ team leader / SoftwareEngineer
/ software designer)
Located in SantiagoDeChile
Personal mailto : gfgschwarz at yahoo dot com
This has to be the homepage with the most links on wiki! It's astonishing how you can use links in sentences!
Before I had access to a computer, I just read BASIC code for simple games from a magazine, until I began to understand them, but I couldn't test them since I had no computer.
I started programming in 1986 on a SinclairSpectrum
, in BASIC, no functions, no subroutines, just GOTO, GOSUB, RETURN, but interestingly a useful abstraction was INPUT, LET, PRINT. The abstraction was: SeparateIoFromCalculation
. See AllAbstractionsLie
. (I don't mean to say abstractions are evil, but that abstractions can be improved).
In 1987, I started a journey at the University of Chile to become a Comp. Sci. Engineer. The first year, I learned Pascal and got rid of GOTO. The third year, I learned indexing and got rid of linear search.
My first programming job was in 1992 when I was still studying, in C++. Tough language, not so tough boss, I became expert by week 10, not because I was a real expert, but there was no-one around to ask anything.
At first, you can create several classes per hour, but as your class library matures, you can DoMoreWithLess
and you create fewer classes and reuse them more. Code 1 hour, debug 1 day was the pace of work. A bug made by someone else bites you, you may be debugging for 3 days if lucky. The solution: UnitTest
s. I didn't automate them fully as CppUnit
does, but it had the same purpose and result. Also, since you debug less, you have more time to refactor your code and you learn OO faster.
After 3 years, I realized C++ was a dead end: Too many rules to remember while at the same time the same thing in Smalltalk was simple and sometimes already solved and you just needed to use it. C++ is faster, yeah right, not really because it takes the whole day to recompile the whole homegrown class library, and because of those blood sucking memory leaks and those core dumps. Besides applications used lots of memory, an Smalltalk app would have used less and be more efficient. Ever wonder there is a better life out there? Absolutely! There is no standard class library in C++ because C++ is not OO. STL is template technology and templates are not OO. Besides templates in C++ are getting slower than Java objects. See http://www.kano.net/javabench/index
for benchmark data.
Work in C++ yet? Of course, if they are willing to pay what it takes. Most rational companies prefer JavaLanguage
, because productivity is higher, programmers become productive faster, time to market is everything, etc. Java programmers are happier because salaries are higher too and they can be home for dinner.
Also benchmarks are showing that Java is catching up on C++. See http://www.idiom.com/~zilla/Computer/javaCbenchmark.html
. Besides, the remaining development time you may use for improving the algorithm.
The main problem with C++ is that it doesn't have ConceptualIntegrity
is impossible because you either embrace it or you simply have an ugly octopus, MultipleInheritance
doesn't work as expected (although some say Eiffel got MultipleInheritance
right, besides Eiffel compiles into C, therefore who needs C++ if you can write in a much better language instead?). See also GenericVsObjectOrientedProgramming
is not SmalltalkLanguage
, but it is so much better than C++ (CeePlusPlus
). See LateCeePlusPlus
. Also JavaUnit
Wrote a short success criteria for a good ClassDiagram
on Wiki. Supposedly it was faster than QuickSort
but it is broken in the InsertPhase?
. Mmmhhh, well next life maybe.
If you've finally given up on this, then it's time to retract the pages you wrote about this. They're quite messy due to all the people arguing with you, and deleting them might be the best cleanup.
Yep, I did remove the page, but someone must have really liked it and took it back to life. It is a excellent example of buggy software, although I prefer the following since I've seen them too many times:
char * fullFilename( char * path, char * filename )
char * ret = malloc( strlen( path ) + strlen( filename ) * 2 );
strcpy( ret, path );
strcat( ret, "/" );
strcat( ret, filename );
What happens when filename == "a"?
Besides, memory should be returned in the same method where it was asked for. I think there is a pattern for this, do you know it's name? AnswerMe
is about Reuse
Reuse can be declared achieved only when a module has been reused for at least 3 times. The RuleOfThree
Reuse is important for any software, not just object oriented software. ComponentOriented
software is supposed to achieve reuse too, but I have almost never reused an EJB. Have you? Reusing WebServices
is simpler when using XSLT transformations, and WebServices
may be implemented using EJB underneath. It's expensive to reuse, but you can do it. Probably using MDB is better than using SessionBeans?
in this case.
If a module is not reusable, it is not ObjectOriented
. If it has not been reused, you can't claim it to be reusable.
. It is useless to release software components if they do not specify their version. If they can communicate, which is usual in distributed environment as J2EE, they should publish each others versions and negotiate a protocol version to talk. Otherwise how do you expect to deploy a new version, all at once? You can't be serious about that.
and other programming practices that I like:
- Make it work.
- ProgrammersShouldTestTheirOwnCode, ideally TestFirst. UnitTest everything using TestCollector. In particular CaptureBugsWithTests as a way to get RegressionTests. InformalCodeReview should concentrate on AutomatedTests, because there may be BugsInTheTests.
- Do ManualTests? besides AutomatedTests?. Create a way for manual tests to be easily selected by the user, so that all the input can be conceptually selected from a button or combo box.
- InformalCodeReview before check-in when no PairProgramming is possible. InformalCodeReview works because DebugByDescribing works.
- Production code should use UnitTests extensively, but Prototypes, Mockups, etc. do not need UnitTests because they are ThrowawayPrototypes?. I would recommend putting them under VersionControl, though.
- If you get some AnalysisParalysis, try a spoon of JustDoIt. In particular: ModelFirst or UiMockupFirst?? JustDoIt EasyThingsFirst.
- Make it right. (ThinkThingsThrough?)
- Avoid operations in which you loose information. The information may not be needed now, but it may be needed in the future. This is an special case of PrematureOptimization. Unless you measured it and you are sure you can't possibly store all that information, strive to AvoidLosingInformation.
- Testing interfaces is wiser than testing classes, because several classes can implement the same interfaces and the interfaces are the ones that should expose behavior. Classes are just implementations: You do not want to exchange an implementation if the whole system may break down.
- Use the appropriate DataStructures instead of using the same DataStructures over and over. DataStructures must be intelligent and have appropriate behavior built in them, instead of putting logic outside the DataStructures. For example, instead of using an array to implement a queue, create a queue class. If objects can't be repeated in a container, use a set. This means that you will always create new containers instead of reusing the old containers. Creating new containers is complicated, but using them is simpler, therefore the bug count will go down dramatically if you GetTheRightAbstractions.
- ReduceScopeOfVariables by DeclareVariablesAtFirstUse using SingleStepConstructor or IsValid() method. Also DeclareVariablesAtFirstUse because ResourceAcquisitionIsInitialization.
- In Java remember to use try-finally for avoiding ResourceLeaks. In C++ destructors took care of that, and that was a very nice and clean, exception safe solution. But anyway, ReleaseResourcesAsSoonAsPossible?, specially if we are talking about the locking/CriticalSection/synchronization objects. The exception to this rule is when you need to write to a file, like a log file, in which case opening and closing the file for each write is obviously a bad idea. I've seen this defect too many times: Several threads try to open the same file at the same time, only one succeeds and the others lock as a ConvoyFormation. Each write operation takes eons, because opening a file is a very expensive operation. Instead keep the file open and cache the data in memory using a synchronized data structure like a Vector or better yet a ConcurrentQueue? that has a thread writing to the file.
- SeparateIoFromCalculation. In ObjectOrientation this is about separating mutator methods from inspector methods.
- SeparateInterfaceFromImplementation?. In particular separate mechanisms from policy as seen on http://www.xml.com/ldd/chapter/book/ch01.html or don't put arbitrary restrictions on implementations. Reusable software should be impossible to use wrong, that means you need to walk the extra mile and sweat when creating reusable libraries, for the ease of use of its interfaces.
- Avoid WriteOnlyCode and specially wizards because WizardsAreDangerous.
- FewShortMethodsPerClass to achieve ThinClasses?. You may use some CodeSmellMetrics.
- No method should have more than 3 parameters.
- DeepClassHierarchies instead of FatClassHierarchies. This seems to be controversial because InheritanceBreaksEncapsulation, but then why use inheritance? If you have DeepClassHierarchies you need RelentlessTesting.
- SinglyRootedInheritanceHierarchy. This is compulsory in JavaLanguage and SmalltalkLanguage. Not so in CeePlusPlus.
- DontRepeatYourself to get WellFactoredCode. OnceAndOnlyOnce and SingleResponsibilityRule when applied to classes leads to easy modification. See SubtractLinesOfCode and CompleteResponsibilityRule.
- Don't betray LiskovSubstitutionPrinciple. UnitTests should fail otherwise.
- Don't betray the LawOfDemeter. TellDontAsk is even stronger, because it concentrates on distributing responsability on more and smaller objects, then it is easier to comply with the LawOfDemeter.
- SelfDocumentingCode by IntentionRevealingNames. This is probably the hardest part of all, unless you have an English major.
- UserInterfaces should allow DirectManipulation of objects. This allows better CodeReuse. ModelViewController as currently implemented doesn't seem to be a step in the right direction. Views should be decoupled from the model, so views should display visual objects which are coupled to model objects, effectively decoupling the views from the model.
- VariableTypes? should all be Interfaces.
- Constants should only be accessible by methods in appropriate classes, so that they can be redefined for subclasses.
- PluggableArchitecture: Create central modules that allow other modules to be plugged in, like GUIs do.
- MethodsShouldBePublic or protected. Never private or package scope. Instance variables should be private.
- SingleFunctionExitPoint is a requisite of StructuredProgramming. ElseConsideredSmelly.
- RefactorMercilessly LowHangingFruit. Also UsingToolsToAvoidCopyAndPasteProgramming.
- DontThrowGenericExceptions. MaskExceptionsAppropriately instead.
- Make it fast.
- ProfileBeforeOptimizing. We all know that IO is several times slower than calculation, but anyway, you never know where the bottleneck is. AsynchronousProgramming using EventQueues is my preferred tool for achieving speed. Memoization is a far second one. Always remember that PrematureOptimization is the root of all evil.
- Other considerations.
- Communicate TechnicalRisk as soon as possible. Try technical RiskMitigation using SpikeSolution.
- Perform EgotistProgramming because LifesJustTooShort.
- Remind that TodoCommentsConsideredHarmful.
- Don't use float or doubles for monetary values. Rounding errors are your enemy in this case. Create a Money class instead that implements operations using a Fraction class or otherwise something more appropriate. This is a GoodThing.
- Be aware of the ThirdVersionEffect. Try to GetTheRightAbstraction.
See Apple's UI guide:
- try http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGIntro/chapter_1_section_1.html
must be consistent, not only with itself, but with what the user is used to. Most users are used to Windows and InternetExplorer
, so most user interfaces should be modelled after that. On the other hand, UI must be reactive: Whenever a user does something, immediately something has to happen (on the screen or otherwise) to signal an acknowledge. For example if the user hovers over a button, the button must pop out immediately. That's a very important feature.
Other than that, DirectManipulation
is king. An ideal UI would be one in which there would be no applications, just data with behavior. For example you receive a new file and you don't know what kind of file this is, automatically the viewer is downloaded from the internet. No installation procedure, once downloaded, it simply asks you...
- Find illumination to find the vision. Vision is what will happen not matter what.
- Define the mission of the system: How the system will get advantage of the vision when it becomes true. The mission will let developers decide what to leave out. This is important because when you reduce the scope you are a lot more closer to the objective.
- BigProjectsThatWork? invariably come from SmallProjectsThatWork?. Make small projects work before you try to get big projects to work.
- Meetings must have a purpose. If there is a problem that meetings are not solving, don't think YetAnotherMeetingWillSolveIt.
- Be aware of the ThirdSystemEffect. Ask developers to tell you when they realize they didn't GetTheRightAbstraction. This requires to avoid the FearCulture.
- TheProcessIsTheProblem. The process must be continually improved to allow people to develop their skills (BecomeCompetent) and apply those skills in the project in a controlled manner (RapidFeedback). Most companies, when implementing CMM in the software development efforts, standardize their documents. That's ok. The only problem is that they do not create a process to standardize those templates, so they repidly become inadequate. Read TomDeMarco's Slack to understand why having a too rigid processes can be efficient, but ineffective.
- DevelopmentServer for ContinuousIntegration acting as a SingleReleasePoint. StagingServer for ManualTests.
- ConcurrentVersionsSystem + CvsWeb. Use ReuseReleaseEquivalencePrinciple to decide how to organize your project in CVS. Everything must go in CVS, even the database scripts. Either PairProgramming or InformalCodeReviewBeforeCheckIn. No development is serious without something like this.
- The database must not be shared. Each developer must have its onw instance of the database. The database must be installed daily from CVS. It should not take longer than a few minutes to do so.
- ContinuousIntegration to avoid IntegrationHell. AutomatedTests must be inside CVS and must be executed after any check-in.
- Divide project in Iterations. Divide Iterations in Modules. Assign experienced developers (TeamLeaders?) to be responsible of each module. Why? If everyone is responsible, no one is.
- GetToKnowYourPeoplesSkills using a TaskDatabase. Using a spreadsheet for controlling what everybody is doing is a waste of time.
- NoSecondChance, but avoid FearCulture.
- RequirementsManagement is exactly equal to Planning and Control. A TaskDatabase like Insecticida is ideal for this.
- Planning and estimation
- RapidEstimates using TaskDatabase. Keep in mind that EstimatesLongerThanThreeDaysConsideredHarmful.
- RapidFeedback. Ideally FeedbackShouldBeFree.
- ProjectUnderControl using TaskDatabase.
- Never NegotiateEstimates. Divide tasks, reassign them or reduce the scope instead.
- SoftwareChangeManagement: Use something like Insecticida (TaskDatabase) to get BalancedScoreCard that indicates how the project is doing. The idea is to improve the process like SEI CapabilityMaturityModel level 5 expects. Adapt it to your project needs with OneHandOnTheYoke.
- Risk management
- TopTenRisks is no substitute for RiskManagement: RiskAssessment and then RiskAvoidance and RiskMitigation. The most important attitude is don't ShootTheMessenger.
- Tasks in TaskDatabase are either 100% or 0% done. Intermediate values are 0% done.
- CodingStandard (or CodingConventions) verified by an automated tool. Conventions must reduce repetitive bugs in your project. Update the conventions to reduce your particular repetitive bugs.
- RegressionTests executed as part of the check-in process. CodeCoverage and MutationTesting too. JDepend and LXR are nice tools to automatically run after check-in.
- PascalLanguage: Structured, fast compilation, StaticallyTyped variables, less prone to HeisenBugs.
- LispLanguage: Functional, minimal, UntypedVariables?, lambdas as a theory of computation, even lambdas are lists.
- PrologLanguage: Execute functions in which variables have not been assigned yet, to find out how can they be assigned. Trivial deduction engine, not so trivial stuff can be implemented in it, as for example natural language engines.
- MlLanguage: Lisp meets StaticallyTyped variables + Java interfaces + CurriedFunctions?.
- HaskellLanguage: MlLanguage + laziness.
- SmalltalkLanguage: ObjectOrientation + blocks (almost lambdas).
- SelfLanguage: ObjectOrientation without classes (ie: without abstractions) and with several compiled methods for a source method. Is this bloatware as templates are?
About ObjectOriented programming
It seems everyone has its own favorite, different and incompatible definition of what ObjectOrientation
This was taken from NygaardClassification
- Object-oriented programming. A program execution is regarded as a physical model, simulating the behavior of either a real or imaginary part of the world.
I'd like to express my sincere disagreement with that classification, only that it says behavior
and I think that in that respect it is correct, too much correct to disagree with the whole phrase, but only I consider that word to be correct, the rest of the text is misleading, IMHO. There is nothing physical, real or imaginary on ObjectOrientation
, at least not more than in other programming paradigms. When you do ObjectOriented
programming, you are modelling the world (the problem domain) using data organized in objects. This is not different from StructuredProgramming
yet. This data has behavior that is organized in classes (object factories). So each object belongs to one and only one factory that fully determines its behavior. If it were not because of the behavior, this would be identical to StructuredProgramming
If it were not because of Inheritance, ObjectOrientation
would be identical to GenericProgramming
. But ComponentProgramming?
does not have PolyMorphism
does have PolyMorphism
, only of the ParametricPolymorphism
kind. See GenericVsObjectOrientedProgramming
I think we need to define what a definition is. A definition is not just an abstraction, because not all abstractions are definitions. A definition is composed of a Definiendum and a Definiens. The definiendum is the set to which it belongs. The definiens is the characteristic that uniquely identifies the concept inside the definiendum.
So, according to that definition of definition, the definition of OOP is:
Definiendum: Programming methodology.
Definiens: Responsibility (of execution) is assigned to classes.
In short we can say OOP is the programming methodology in which responsibility (of execution) is assigned to classes.
This requires a definition of class. A class is an object that creates other objects and that determines the behavior of those objects through the specification of the messages they can respond to by the definition of the corresponding methods and by the use of inheritance of classes.
This requires a definition of inheritance of classes. Inheritance of classes is a property of classes that allows classes to use methods defined in other classes as if they were their own, while at the same time, when the reused methods are executed, unknowingly they may send messages to the class that is reusing them.
This is just an specification of PolyMorphism
, IMHO, is ResponsibilityDrivenDesign
through the use of PolyMorphism
achieved by inheritance and encapsulation.
says that ObjectOrientationIsaHoax
because you first gotta find the interesting algorithms
and then you can find the appropriate data structures, as in mathematics you first find the interesting theorems and then you find the axioms, not the other way around. ObjectOrientation
, in his point of view, therefore is: Find the axioms (the classes), then find the algorithms (the methods).
is not about finding first one or the other, you can find either. But forcing developers to first find the algorithms is probably wrong. The algorithms are not interesting
, they must just solve a problem in an object space. Maybe that's the reason why STL has not come up with anything useful.
argues that he has never seen interesting code from ObjectOriented
developers. Maybe that's the whole point of ObjectOrientation
. No piece of code is the central idea
of an ObjectOriented
program. But interesting code is not about being enamored of a thousand lines, it is about usefulness. See BitBlt?
and the GUI, those are good examples that ObjectOrientation
works. Do you have anything like those in STL? STL simply doesn't work, it is just interesting for mathematicians, not for real work, because you must know everything in advance (all the theorems) before anything can be done (the right axioms are elusive). See GoedelsIncompletenessTheorem
. STL is not dynamic, you can't change its behavior incrementally, so you either have everything or you have nothing. That's not a model of programming I would like to work in.
I agree that if ReuseHasFailed
, but only in the context of your project. My projects achieve reuse because I always take the time to think in the DependencyInversionPrinciple
and try to apply it to the classes I create, so whatever they try to achieve, they do using the narrowest possible requirements and they solve the problem they are trying to solve in the most general way. This means I spend a lot of time refactoring to GetTheRightAbstraction
, but usually it is time well spent. The usual analogy I use is the stair: If you want to get to the 20th floor using a stair, it is faster if you do it step by step.
First Questions when entering any new project
- Is there a CVS server (or another CodeRepository?) where the code is being stored?
- Are automated tests being stored in the same CVS server where the code is being stored?
- Are automated database scripts being stored in the same CVS server where the code is being stored?
- Are there independent databases for each developer, so that each developer may create the database from the scripts in CVS?
- Is there an IntegrationServer? that performs daily builds to verify that the code CVS still compiles and that all automated tests still pass?
- Is there an implementation plan in a TaskDatabase? In XP the implementation plan is called ReleasePlan.
- Is there a CodingConvention document in CVS?
- Are there user manuals in CVS for each of the modules?
- Is there a StagingServer that allows to perform ManualTests? on what is being implemented according to the user manuals?
- Is there anything already implemented that is manually testable, even if it is just doing login/logout and navigating the menus?
My opinion is that by using Closures you feel motivated to create all closures in advance and then just use them. In other words, if you want to print the elements in a collection:
class PrintClosure? extends Closure
public void exec( Object item )
System.out.prinln( item );
Then you use it like this:
collection.forEach( new PrintClosure?() );
This can be important for writing things OnceAndOnlyOnce
. Besides, if the underlying DataStructure
changes, it is easier to just reimplement forEach instead of changing all those for loops.
About MemoryLeaks in JavaLanguage
A memory leak is a piece of memory that is not accessible to the program or to the <i>garbage collector</i> (tm).
A dangling reference is when a single piece of memory is used by two objects as if it were their own, because some object called delete on another, but there was a reference somewhere to the deallocated object. This can't happen in Java, but it can happen still in C++ and C# (for unmanaged code).
A buffer overflow occurs when an array is accessed using an index out of range and no ArrayIndexOutOfRangeException?
is thrown. Again: This can't happen in Java, but it can happen still in C++ and C# (for unmanaged code).
An unused memory reference by class invariant leak is memory that can be accessed by the program, but the class invariant does not permit to access it. For example you implement an stack in an array and forget to null out elements when popping the stack.
About Silver Bullets
People who believe in magical cure-alls for tough problems are stupid. Stupidity is incurable, chronic, and debilitating. Ignorance, on the other hand, is curable even when it is acute. We can't do anything about stupidity, but we have a responsibility to fight ignorance.
-- Taken from http://www.neward.net/ted/weblog/index.jsp
There is no silver bullets, but a bunch of silver bullets working together can do a big difference.
Contents under pressure sanitized for your protection. Approved for veterans.
List was current at time of printing. Use only as directed.
No purchase necessary.
Some equipment shown is optional. May be too intense for some viewers. Not recommended for children.
Don't read this while driving. For off-road use only. Do not use while operating a motor vehicle or heavy equipment.
Do not use if pregnant. If condition persists, consult your physician. Discontinue if rash appears.
We reserve the right to make changes or substitutions without notice.
Slippery when wet. Your mileage may vary.
during this production. Objects in mirror are behind you. Not for the faint-of-heart.
Do not write below this line.
Ubuntu 10.4 doesn't recognize the wireless card out of the box on Compaq Presario F500.
It took me days to find the solution. Here it is:
cat > enable-wireless.sh <<Done.
sudo apt-get install build-essential
tar xjf b43-fwcutter-011.tar.bz2
tar xjf broadcom-wl-220.127.116.11.tar.bz2
echo Running ../../b43-fwcutter-011/b43-fwcutter -w "$FIRMWARE_INSTALL_DIR" wl_apsta.o
sudo ../../b43-fwcutter-011/b43-fwcutter -w "$FIRMWARE_INSTALL_DIR" wl_apsta.o
Installing the Sun Java compiler on Ubuntu:
- sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
- sudo aptitude update
- sudo aptitude install sun-java6-jdk
doesn't seem to work in Ubuntu 10.4 yet, a pity. Use qct (graphical commit) and meld (diff) instead, installing them using the usual sudo apt-get install command.