Guillermo Schwarz

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: UnitTests. 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, ObjectOrientation 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.

JavaLanguage is not SmalltalkLanguage, but it is so much better than C++ (CeePlusPlus). See LateCeePlusPlus and StlSucks. Also JavaUnit rocks.

Wrote a short success criteria for a good ClassDiagram.

Published SchwarzMergeSortAlgorithm? 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 );
   return ret;
}

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.


ObjectOrientation is about Reuse

Reuse can be declared achieved only when a module has been reused for at least 3 times. The RuleOfThree applies here?

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.

See ReuseReleaseEquivalencePrinciple. 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.


ObjectOriented and other programming practices that I like:

  1. Make it work.
    1. 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.
    2. 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.
    3. InformalCodeReview before check-in when no PairProgramming is possible. InformalCodeReview works because DebugByDescribing works.
    4. 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.
    5. If you get some AnalysisParalysis, try a spoon of JustDoIt. In particular: ModelFirst or UiMockupFirst?? JustDoIt EasyThingsFirst.
  2. Make it right. (ThinkThingsThrough?)
    1. 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.
    2. 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.
    3. 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.
    4. ReduceScopeOfVariables by DeclareVariablesAtFirstUse using SingleStepConstructor or IsValid() method. Also DeclareVariablesAtFirstUse because ResourceAcquisitionIsInitialization.
    5. 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.
    6. SeparateIoFromCalculation. In ObjectOrientation this is about separating mutator methods from inspector methods.
    7. 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.
    8. Avoid WriteOnlyCode and specially wizards because WizardsAreDangerous.
    9. FewShortMethodsPerClass to achieve ThinClasses?. You may use some CodeSmellMetrics.
    10. No method should have more than 3 parameters.
    11. DeepClassHierarchies instead of FatClassHierarchies. This seems to be controversial because InheritanceBreaksEncapsulation, but then why use inheritance? If you have DeepClassHierarchies you need RelentlessTesting.
    12. SinglyRootedInheritanceHierarchy. This is compulsory in JavaLanguage and SmalltalkLanguage. Not so in CeePlusPlus.
    13. DontRepeatYourself to get WellFactoredCode. OnceAndOnlyOnce and SingleResponsibilityRule when applied to classes leads to easy modification. See SubtractLinesOfCode and CompleteResponsibilityRule.
    14. Don't betray LiskovSubstitutionPrinciple. UnitTests should fail otherwise.
    15. 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.
    16. SelfDocumentingCode by IntentionRevealingNames. This is probably the hardest part of all, unless you have an English major.
    17. 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.
    18. DoMoreWithLess.
    19. VariableTypes? should all be Interfaces.
    20. Constants should only be accessible by methods in appropriate classes, so that they can be redefined for subclasses.
    21. PluggableArchitecture: Create central modules that allow other modules to be plugged in, like GUIs do.
    22. MethodsShouldBePublic or protected. Never private or package scope. Instance variables should be private.
    23. SingleFunctionExitPoint is a requisite of StructuredProgramming. ElseConsideredSmelly.
    24. RefactorMercilessly LowHangingFruit. Also UsingToolsToAvoidCopyAndPasteProgramming.
    25. DontThrowGenericExceptions. MaskExceptionsAppropriately instead.
  3. Make it fast.
    1. 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.
  4. Other considerations.
    1. Communicate TechnicalRisk as soon as possible. Try technical RiskMitigation using SpikeSolution.
    2. Perform EgotistProgramming because LifesJustTooShort.
    3. Remind that TodoCommentsConsideredHarmful.
    4. 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.
    5. Be aware of the ThirdVersionEffect. Try to GetTheRightAbstraction.

See Apple's UI guide:

http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGPartI/chapter_2_section_1.html#//apple_ref/doc/uid/20000957-CH232 (BrokenLink - try http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGIntro/chapter_1_section_1.html).

UserInterfaces? 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...


Interesting ProjectManagement practices:

  1. General
    1. Find illumination to find the vision. Vision is what will happen not matter what.
    2. 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.
    3. BigProjectsThatWork? invariably come from SmallProjectsThatWork?. Make small projects work before you try to get big projects to work.
    4. Meetings must have a purpose. If there is a problem that meetings are not solving, don't think YetAnotherMeetingWillSolveIt.
    5. Be aware of the ThirdSystemEffect. Ask developers to tell you when they realize they didn't GetTheRightAbstraction. This requires to avoid the FearCulture.
    6. 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.
  2. Organization
    1. DevelopmentServer for ContinuousIntegration acting as a SingleReleasePoint. StagingServer for ManualTests.
    2. 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.
    3. 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.
    4. ContinuousIntegration to avoid IntegrationHell. AutomatedTests must be inside CVS and must be executed after any check-in.
    5. 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.
    6. GetToKnowYourPeoplesSkills using a TaskDatabase. Using a spreadsheet for controlling what everybody is doing is a waste of time.
    7. NoSecondChance, but avoid FearCulture.
  3. RequirementsManagement is exactly equal to Planning and Control. A TaskDatabase like Insecticida is ideal for this.
  4. Planning and estimation
    1. RapidEstimates using TaskDatabase. Keep in mind that EstimatesLongerThanThreeDaysConsideredHarmful.
    2. RapidFeedback. Ideally FeedbackShouldBeFree.
    3. ProjectUnderControl using TaskDatabase.
    4. Never NegotiateEstimates. Divide tasks, reassign them or reduce the scope instead.
    5. 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.
  5. Risk management
    1. TopTenRisks is no substitute for RiskManagement: RiskAssessment and then RiskAvoidance and RiskMitigation. The most important attitude is don't ShootTheMessenger.
    2. Tasks in TaskDatabase are either 100% or 0% done. Intermediate values are 0% done.
    3. 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.
    4. 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.


Nice languages:


About ObjectOriented programming

It seems everyone has its own favorite, different and incompatible definition of what ObjectOrientation is.

This was taken from NygaardClassification:

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 or ComponentProgramming?. But ComponentProgramming? does not have PolyMorphism. GenericProgramming does have PolyMorphism, only of the ParametricPolymorphism kind. See GenericVsObjectOrientedProgramming and StlSucks.

Regarding NobodyAgreesOnWhatOoIs

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.

Any questions?

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.

ObjectOrientation, IMHO, is ResponsibilityDrivenDesign through the use of PolyMorphism achieved by inheritance and encapsulation.

Regarding ObjectOrientationIsaHoax

AlexanderStepanov 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).

IMHO, ObjectOrientation 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.

AlexanderStepanov 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.

Regarding ReuseHasFailed

I agree that if ReuseHasFailed then ObjectOrientationHasFailed?, 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

  1. Is there a CVS server (or another CodeRepository?) where the code is being stored?
  2. Are automated tests being stored in the same CVS server where the code is being stored?
  3. Are automated database scripts being stored in the same CVS server where the code is being stored?
  4. Are there independent databases for each developer, so that each developer may create the database from the scripts in CVS?
  5. Is there an IntegrationServer? that performs daily builds to verify that the code CVS still compiles and that all automated tests still pass?
  6. Is there an implementation plan in a TaskDatabase? In XP the implementation plan is called ReleasePlan.
  7. Is there a CodingConvention document in CVS?
  8. Are there user manuals in CVS for each of the modules?
  9. Is there a StagingServer that allows to perform ManualTests? on what is being implemented according to the user manuals?
  10. Is there anything already implemented that is manually testable, even if it is just doing login/logout and navigating the menus?


Interesting Discussions

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.

-- GuillermoSchwarz


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.


Disclaimer

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. NoAnimalsWereHarmed during this production. Objects in mirror are behind you. Not for the faint-of-heart. Do not write below this line.


About Ubuntu

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:

   mkdir enable-wireless
   cd enable-wireless
   cat > enable-wireless.sh <<Done.
   sudo apt-get install build-essential
   mkdir Drivers
   cd Drivers
   mkdir wireless
   cd wireless/
   wget http://bu3sch.de/b43/fwcutter/b43-fwcutter-011.tar.bz2
   tar xjf b43-fwcutter-011.tar.bz2
   cd b43-fwcutter-011
   make
   cd ..
   export FIRMWARE_INSTALL_DIR="/lib/firmware"
   wget http://downloads.openwrt.org/sources/broadcom-wl-4.80.53.0.tar.bz2
   tar xjf broadcom-wl-4.80.53.0.tar.bz2
   cd broadcom-wl-4.80.53.0/kmod
   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
   Done.
   . enable-wireless.sh


Installing the Sun Java compiler on Ubuntu:

  1. sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
  2. sudo aptitude update
  3. sudo aptitude install sun-java6-jdk


TortoiseHg? 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.


CategoryHomePage


EditText of this page (last edited August 23, 2013) or FindPage with title or text search