Thursday, December 31, 2009

Computer Science vs. Software Engineering

I listened to SE-Radio Episode 149: Difference between Software Engineering and Computer Science with Chuck Connell.

Interesting stuff...

The most insightful thing was that historically we put too much unrelated things into the same bucket:
  • Computer Science vs. Software Engineering
  • Algorithms, Cryptography, Compilers vs. Business Applications, Consumer Applications
  • Complexity Analysis, Correctness Proofs vs. Maintainability, Testability
  • Formal Specifications vs. Estimation
  • Language Syntax/Semantics vs. Design Patterns

  • More background is in Chuck Connells article on Dr.Dobb's. Including The bright line in computer science:
    090604connell_f1.gif
    This once again leads back to the question: What is software engineering?
  • Art?
  • Craftmanship?
  • Science?

  • Wednesday, December 30, 2009

    Bug Driven Development: Samurai Debugging Reinvented

    Mechanical_bug.jpg In his presentation about Behavior Driven Development (BDD) and Domain Driven Design (DDD), Dan North talks about another interpretation of "BDD": Bug Driven Development or "DDD": Defect Driven Development.

    It goes like this:

    The customer comes to the developer and wants the perfect system. He describes what he wants, but its this fuzzy vision described in a business language that the developer just is not able to grasp...

    The developer: "Ah ok... I understand. It is done!"

    Customer: "What? What do you mean?"

    Dev: "Well it is done. The system is finished!"

    Customer: "Well, no ... I don't see an icon where I can start the system?"

    Dev: "Oh! You are right. That's a bug! I will fix it."

    ... five minutes later ...

    Dev: "Ok, the icon is here. Now it is done!"

    Customer: "Well, no! When I double-click the icon nothing happens!"

    Dev: "Oh! You are right. Thats a bug! I will fix it."

    ... five minutes later ...

    Dev: "Ok, the the app starts when you double click. Now it is done!"

    Customer: "Well, no! There is nothing in the newly opened window!"

    Dev: "Oh! You are right. Thats a bug! I will fix it."

    ... you get the idea.


    While this is a humorous story, it actually demonstrates the qualities that BDD (now Behavior Driven Development again) strives for:
  • Pull based instead of push based: The developer pulls new requirements from the business just in time when they are needed.
  • Outside-in: The development is driven by the business relevant features that are actually used and matter to the stakeholder.
  • Constant involvement of the customer.
  • Small steps with clear acceptance criterias.

  • Another analogy is funny: Behavior Driven Development is an evolvement from Test Driven Development, taking the concepts of the latter to a higher level, evolving out of a purely developer-centered discipline.

    The same could be said for Bug Driven Development: The concept of Samurai Debugging was already a humorous technique in Extreme Programming:
    When you follow the Samurai Debugging technique, you start with a blank screen. That's not what you want, so you start debugging it, and you continue debugging it until your program does exactly what you want it to do.

    Now Bug Driven Development takes this to the next level by involving the customer :-).

    Tuesday, December 29, 2009

    Java vs. Net: Web Frameworks

    Quantity is the real difference:
    Screen shot 2009-12-29 at 7.06.16 PM.png

    Humorous episodes following from this:
    Trolling with Java Web Frameworks.
    I don't think you can count someone even as a semi-decent java dev until he wrote his very own web framework at least once in his life (from here)

    Monday, December 28, 2009

    Code Monkeys do exist: I knew it!

    Ever felt like a Code Monkey?

    Then Primate Programming Inc might be the company for you...
    Screen shot 2009-12-28 at 12.36.44 PM.png
    "Humans and higher primates share approximately 97% of their DNA in common. Recent research in primate programming suggests computing is a task that most higher primates can easily perform. Visual Basic 6.0™ was the preferred IDE for the majority of experiment primate subjects."

    Thursday, December 24, 2009

    Definition of Behavior Driven Development

    images.jpg I updated the entry for Behavior Driven Development on Wikipedia.

    On the Agile Testing, Specifications and BDD exchange Dan North gave an updated definition of BDD in his talk:

    BDD is a second-generation, outside-in, pull- based, multiple-stakeholder, multiple-scale, high-automation, agile methodology. It describes a cycle of interactions with well- defined outputs, resulting in the delivery of working, tested software that matters.
    Watch his talk for an explanation of this definition...

    Wednesday, December 23, 2009

    Maven gets partially absorbed by modern JVM languages …

    matroschka250pxMaven has a lot of interesting and useful ideas, but its usage is often over-complicated and several concepts are too much entangled. (examples: 1, 2, 3)

    The foremost feature of Maven that comes to mind is probably dependency management. Maven probably standardized dependency management for the Java platform. That’s probably also the reason for its wide adoption.

    At this time there are already several attempts for smaller and easier solutions that repackage the ideas about dependency management from Maven. Their promise is to be a cleaner and easier to use.

    Foremost there is Ivy, which provides Maven-like dependency management for Ant.

    There are even two JRuby projects that bring simplified Maven-like dependency management to the JVM: maven_gem and javagems.

    Especially interesting is Grape, which provides dependency management for Groovy at a language level (by integrating Ivy).

    I think these examples are an impressive demonstration how the Java platform grows and how good ideas and concepts are adapted and evolved.

    Monday, December 21, 2009

    Challenging Requirements Video

    Screen shot 2009-12-20 at 11.10.20 PM.png Definitely the most entertaining presentation (closely followed by Dan North's) at the Agile Testing, Specifications and BDD exchange was Gojko Adzic's "Challenging Requirements".

    You can watch a video of his presentation on his blog.


    puzzle.png I can also recommend Gojko's latest book: Bridging the communication gap.

    It is a very good resource for learning ATDD and BDD.

    Monday, November 16, 2009

    Poignant statements about our profession

    cliff diver ad.jpgJay Fields has a poignant but concise style to express his opinion.

    Currently my two favorite quotes are:
    We're still figuring this stuff out. All of us.

    Thoughts on developer Testing

    and
    When no one knows what's "correct", people with confidence generally win the discussion.

    Programmer Confidence and Arrogance


    Wednesday, November 11, 2009

    A note to all software project stakeholders: Remember it is not christmas!

    Peter Stevens hit the nail on the head at the SAQ Software Tester Forum 2009 last week:
    You won't get everything you want!

    That's a fact. Accept it.

    Actually you can get everything you want if you have unlimited time and money. But since that is not the case in todays software projects (maybe there are exceptions?), we have to make tradeoffs.
    And that is where the strength of Agile Software Development comes into play.

    Agile advocates constant feedback and prioritization. Together with the 'good enough' and YAGNI principles this helps to create better usable systems within budget and time constraints (eliminate waste in the lingo of the lean).

    Peter Stevens then talked about how goals can still be achieved, even without getting everything we want. His presentation can be downloaded here.

    Later on, in an interesting conversation Andy Palmer pointed out that even when a MoSCoW (Must, Should, Could and Won’t) analysis is done, still a lot of projects finally only deliver a fraction of the actual 'Musts' ... and are still considered as a success. What does this tell about our prioritization?

    Monday, November 9, 2009

    Testing: Chances and Challenges in an Agile World

    Last week I gave a presentation on the SAQ Software Tester Forum 2009:
    Testing: Chances and Challenges in an Agile World (most slides in english...)
    View more documents from jbandi.
    Update 2009-11-11: Here are some pictures of the event.

    The stage for my presentation was very well set by Andy Palmer and Peter Stevens who talked both about Acceptance Test Driven Development and about Agile Development in general.

    In the afternoon there were several discussion sessions. Generally people wanted to know what the major changes there are in agile projects concernig testing.

    A lot or the participants were very eager to affirm that Agile does not change anything concerning testing. Somehow I got the feeling that there was a fear that Agile is claiming that traditional testing is somehow outdated or superfluous...

    In my opinion this is definitely not the case. Solid testing practices and processes are even more important in Agile projects. What changes is the timeline! This however has implications on the amount of work (a lot more test effort aggregated over the whole project) and it is a challenge for tester how to deal with this. But it does definitely not change that testing in all flavors (automated, manual, guerillia ...) is still a must.

    If I look at requirements engineering, development and testing as three separate disciplines in software projects, then I would argue, that Testing is actually the discipline that is the least affected by Agile.

    puzzle.png Most of the participants however were very focused on their current situation and activities and not seeing the big picture. Tests to assert quality is and will always be important. But testing can be more than quality assurance! Tests can be leveraged to prevent defects. Of course this is not necessarily bound to Agile, but Agile explicitly supports those notions.

    One consequence of these ideas however is that developers and testers have to interact intensely and there is no place any more for traditional boundaries between testers and developers! Agile promotes multifunctional teams. This however does not mean that there are no specialized testers any more, but they are part of the same team as the developers and all have the common goal of producing useful software. Games of queen of spades between developers and testers definitely have no place in an Agile project!

    Dollar Sign 3.jpg In the final panel discussion Peter Stevens pointed out another perspective, that shows that testers can greatly profit from Agile: In traditional enterprisey environments the salary curve is usually inverse proportional to the distance to the customer. Testers sit at the end of the chain, with the greatest distance to the customer. This setup can change drastically with Agile ideas like formulating Acceptance Tests with the customer, moving Acceptance Tests to the beginning of development and driving development with Acceptance Tests. Open minded testers can seize this chance and redefine their role in the organization hierarchy!

    Monday, November 2, 2009

    Quick Tip: Running Selenium on OS X Snow Leopard

    Probably it is not only a Snow Leopard thing. But I stumbled over the following problems when running Selenium on OS X:

    With Safari 4.0.3: Pop-up blocking is default on, switch it off:
    Screen shot 2009-11-02 at 12.24.29 AM.png


    With Firefox 3.5.3:
    I got the following error from the selenium server:
    dyld: Library not loaded: /usr/lib/libsqlite3.dylib
      Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security
      Reason: Incompatible library version: Security requires version 9.0.0 or later, but libsqlite3.dylib provides version 1.0.0

    This problem was fixed with copying a newer version of the library into the firefox installation:
    mv /Applications/Firefox.app/Contents/MacOS/libsqlite3.dylib /Applications/Firefox.app/Contents/MacOS/libsqlite3.dylib.orig
    cp /usr/lib/libsqlite3.dylib /Applications/Firefox.app/Contents/MacOS/libsqlite3.dylib
    
    (First command is just for backup. Tip found here)


    Update: 2010-11-14: For Firefox 3.6 make sure that you are upgrade to the latest version of selenium-server. I just wasted some hours trying to get firefox running with selenium-serve 1.0.1. The problem disappeared with selenium-server 1.0.3.

    Thursday, October 29, 2009

    SpecFlow - Pragmatic BDD for .Net

    Some days ago TechTalk released SpecFlow as an open source project.

    Unbenannt.png

    The mission of SpecFlow is to provide a pragmatic and frictionless approach to Acceptance Test Driven Development (ATDD) and Behavior Driven Development (BDD) for .NET projects today.

    The main website is at www.specflow.org
    The source code is hosted on GitHub: SpecFlow.
    The wiki and issue tracking is at code.google.com/p/specflow

    We at TechTalk are successfully using SpecFlow in several projects.

    SpecFlow was mainly developed on the background that using Cucumber on the .Net platform is currently painful and not frictionless at all. You can read more on Gaspars Blog.

    SpecFlow was heavily inspired by Cucumber. It aims at bridging the communication gap between domain experts and developers by binding business readable behavior specifications to the underlying implementation.

    To get an idea how this can be realized:

    First write your scenarios in plain-text...step1.png

    ... then let SpecFlow execute them! step7.png

    Wednesday, October 21, 2009

    Büroeröffnung TechTalk Schweiz im Technopark Zürich - Vortrag agiles Testen mit ATDD und BDD

    Update 2009-11-18: Slides are published on SlideShare

    My company TechTalk is officially opening its new office in Switzerland next Wednesday October 28 in Zurich's Technopark.

    Christian and I will hold a technical Talk about realizing agile Testing with Acceptance Test Driven Development (ATDD) and Behavior Driven Development (BDD).

    Milton & Red Swingline.bmp Everybody is invited, entrance is free.

    The talk starts at 16:30. Here is the official announcement. I would happy to see you there.

    Thursday, October 1, 2009

    Learned today: Scrum is like a roundabout

    Yesterday I was attending the scrum breakfast in Bern.

    François Bachmann held an insightful presentation where he drew analogies between traffic and software projects: Projektstau auflösen - wie Sie Ihrem Manager Agilität erklären können (Breaking up traffic jam - how you can explain Agile to your manager).

    roundabout.pngThe main analogy was:
    Scrum is like a roundabout
  • Simple & Transparent Concept
  • Based on the Pull principle (not Push)
  • Provides Feedback
  • Self-organising mechanism
  • Heavily relies on discipline and personal responsibility
  • Roundabouts cause uncertainty and precaution at first contact (if you are used to traffic lights - command & control style).
  • Roundabouts are optimized for local decisions (only precedence from one direction is relevant) - traffic is too complex for exact planning and influenced by unforeseeable events, only high level planning is feasible, details have to taken care of when they happen.
  • A lot of decision-makers with potential different interests are involved
  • Individual decision-makers have only incomplete informations
  • Roundabouts work as well for rush-hours as for no-traffic situations
  • Benefits: less conflict, higher safety, optimized throughput, reduced waste, reduced costs, calm & aesthetic
  • Problems: Not appropriate for some situations (highway crossing a footpath), requires space, needs getting used to

  • 531312153_9f1bef580b.jpg
    And a funny example of scrumbut:
    Arc de Triomphe - a roundabout, but entering vehicles have precedence.

    Wednesday, September 30, 2009

    Retrospective: JPA Workshop /ch/open

    image_thumb.png Simon and I gave our JPA Workshop at the workshop days of /ch/open earlier this month.

    Now the course feedback is online. I think generally we can be content, especially the comments are pleasant. The participants seemed to like our examples.

    All the content (slides and examples) is available as project jpaworkshop on Kenai.

    I am looking forward to repeating the workshop next year. By then the JPA2 implementations should be finished.

    Note to myself - things to look into for the next time:
  • Using EclipseLink JPA Extensions for Entity Caching
  • Understanding EclipseLink Caching
  • Queries and the Cache
  • EclipseLink/Examples/JPA/Pagination -> still supporting only Oracle?

  • Tuesday, September 29, 2009

    Abstraction, Encapsulation and social Darwinism (The Antipattern of Framework- vs. Business-Programmers)

    Responsibility trap number one: Building a platform to make other (lesser) programmers more productive.

    - Eric Evans at SET 2008


    Hiding things from developers often requires more effort in the long run than simply trying to educate your developers as to how they should properly do their job.

    - Educate Developers Instead Of Protecting Them by Davy Brion


    Making development "safe" for lesser skilled developers by taking choices away from developers [...] does far more to hamper the efforts of your best developers than it does to make weaker developers more productive. I'll say that there is a silver bullet(s), it's: Skill. Knowledge. Experience. Passion. Discipline.

    - Jeremy Miller


    Again and again I come across projects, teams and companies that misuse the concepts of Abstraction and Encapsulation to establish a two class society among the developers.

    mind_the_gap-logo.jpg In those setups you usually find on one side a framework-team that is responsible for a supposedly productivity-boosting, supposedly well crafted framework / platform / infrastructure. On the other side you find an army of business programmers that have to use the provided framework / platform / infrastructure to actually realize business value.

    Usually the framework-team members think of themselves as the gurus, the elite, the "real" programmers, while the business programmers are considered as "lesser" foot soldiers.
    These attitudes are mostly shared and therefore promoted by management. Indeed the framework-programmers often have the better education and/or more technical expertise.
    If the situation is really bad then the framework team does not like to mingle with the business-programmers and the worst thing is, when they are not even co-located.

    Teamwork.gif I heavily oppose this setup. It is an antipattern, that prevents team enabling. Agile, self-enabling, highly-motivated teams will never evolve in such a structured and divided team setup. This is not an environment where individuals are allowed to grow, this is an environment where employees are assigned! In such an environment, people just start to not care any more: framework-developers do not really care about business value, business-developers dont't feel like being able to make a difference...

    As I don't believe in the factory analogy, I don't believe there is a situation where lesser developers have to be shielded/protected by a technical framework. The time to create a patronizing framework, would be better invested in teaching and exchanging knowledge.
    In my experience, if a developer is not productive, then this is usually a management failure. Simple measures like assigning another task, changing the setup, pair programming, coaching, reviews etc. would usually improve the situation. I have seen projects where this has been achieved successfully, but in the above setup, this is usually not going to happen.
    And in the rare case that you are really dealing with a net negative producing programmer (NNPP), no technological solution will save you... Abstraction and Encapsulation are pillars of object-oriented design. They are intellectual constructs to tackle complexity. They are technical tools and not a mechanism to legitimate team structure.

    Using engineering techniques from object-oriented design to enforce team structure and separation feels just as wrong as applying Darwin's evolution theory to human societies.

    medicine20logo.jpg Possible remedies and counter measures for the situation are:
  • Eat your own dogfood: Framework-developers have to use their own framework. They have to be involved in business-programming.
  • Empower the business developers: Establish an environment where it is absolutely clear, that the business developers are the ones that are providing value. The framework-team has the sole purpose to enable the business-developers.
  • Productize the framework: Nobody is forced to use the framework. The framework-programers have to actively sell their work, the business developers can freely decide if they want to use it. (According to a disscussion with Mark Striebeck, this philosophy is very successful at Google)
  • Collective ownership of the code, including the framework.

  • Monday, September 28, 2009

    Geek and Geekess Humor

    braindead-closeup.jpg
    Geeks fantasies:
    If browsers were women...

    And here is the female reaction:
    If your browser was a dude...

    Tuesday, September 22, 2009

    Illustrative Programming: I am a skeptic! (and I am not alone)

    I have stated several times, that I don't believe in visual modeling and cannot share the enthusiasm that a certain branch of MDSD people have for visual modeling:

    Now Martin Fowler is coining the Term "Illustrative Programming" in the context of Language Workbenches like IntentionalSoftware, which are tools to build "illustrative DSLs".

    For a lot of people coming from the UML camp, the notion of a "DSL" is what Fowler is calling an "illustrative DSL" here. Visual Studio Domain-Specific Language Tools are a striking example of this.

    In his article Martin Fowler quotes some opinions of Neal Ford about the concepts of Illustrative Programming:
  • I think these tools work best for lay people (thus, your link to LayProgrammers). However, in general, tools like this slow down experienced/power users. [...] I would much prefer a markup language I could use to directly define stuff, with macros, snippets, and all the other things I'm accustomed to as a developer.
  • As these tools grow, they get unwieldy (perhaps because they are ceasing to be domain specific enough?). [...] APIs in programming languages scale much better, with several orders of magnitude more density before they become hard to navigate.
  • All the best-practices and tools don't exist there: refactoring, levels of testing, etc. Also, you loose the connection to text, meaning that macro facilities either don't exist or complex one-offs. [...]
  • I share your bullishness around these types of tools, but they are a long time from being useful for full-bore Agile development. I hope they mature fast.

  • webdesign.jpg Reading these comments, I am having a deja-vu!

    This is really expressing what I was feeling when I was involved in MDSD attempts in recent projects. I don't generally doubt the noble goals that the visual modeling camp believe in.

    But the tools and environment are just not ready to provide value. At least not in that kind of mainstream real world enterprise projects I have been involved in.

    Also in my experience, the target of illustrative programming is the developers, which is wrong!

    As Fowler is pointing out, the goal of illustrative programming is to engage lay-programmers.
    Developers need other tools than lay-programmers! So if there are no lay-programmers in your project, there is arguably need for illustrative programming...

    This insight was always lacking when I was confronted with attempts at visual modeling.

    It is a common mistake in a lot of projects to establish some kind of two-class society among the developers, in this case it could be tempting to degrade the second class to lay-programmers. But that is a sick environment to begin with (and the topic for another post)...

    Monday, September 21, 2009

    Quick Tip: Additional File Types for OS X Quick Look

    As I am diving into cucumber, I would like OS X Quick Look to display my .feature files.
    (and while I was already at it, I also enabled Quick Look for .properties and .textile files)

    This is what I did:
  • I navigated into the TextMate package (right-click->Show Package Contents).
  • I edited Contents/Info.plist with a text-editor.
  • I added the follwing snippet at the end of Info.plist (just before the ending </dict> </plist>)
  • <!-- inserted jb, 20090920 for QuickLook improvement -->  
    <key>UTExportedTypeDeclarations</key>  
     <array>  
       <dict>  
         <key>UTTypeConformsTo</key>  
         <array>  
           <string>public.text</string>  
            <string>public.plain-text</string>  
         </array>  
         <key>UTTypeDescription</key>  
         <string>Code</string>  
         <key>UTTypeIdentifier</key>  
         <string>com.macromates.textmate</string>  
         <key>UTTypeTagSpecification</key>  
         <dict>  
           <key>com.apple.ostype</key>  
           <string>TEXT</string>  
           <key>public.filename-extension</key>  
           <array>  
             <string>properties</string>  
             <string>textile</string>  
             <string>feature</string>
           </array>  
         </dict>  
       </dict>  
     </array>
    
  • Then I set TextMate as the default editor for .feature files.
  • Finally I nudged the system o tell it something has changed with touch /Applications/TextMate.app and qlmanage -r on the commandline.

  • The result:
    Picture 3.png

    Thursday, September 17, 2009

    Need a break - care for a flame-war?

    flame.jpg If this is another of those days, getting bogged in the trenches of enterprise IT, here might be your entertaining break:

    There is an exceptional flame-war going on between Alex Yakunin of ORMBattle.net and Ayende!

    Some of the skirmishes are listed here:
  • The beginning: ORM Battle.net: The ORM Tool Shootout
  • The main battle lead by Ayende: Benchmarks are useless, yes, again (check out the comments ...)
  • Ayende: Benchmark cheating, a how to
  • Alex: Are results of this test suite really important? Part 1. Why I don't believe Oren Eini.
  • Ayende: How to lose respect and annoy people


  • And if this is not enough, check out this flame-war of Bob Lee and Gavin King: Comments on "Annotations for Dependency Injection"

    Monday, September 14, 2009

    The passionate developer: I do like my profession, I don't like my job

    Update 2009-09-14: There are interesting discussions of this post on hackernews. Thanks!

    To only a fraction of the human race does God give the privilege of earning one’s bread doing what one would have gladly pursued free, for passion. I am very thankful.

    The Mythical Man Month, p. 291


    Architects, designers, and developers of corporate systems usually have little or no voice in what gets built, or how, or why. They don't sign on, they get assigned. I know that individual developers do care passionately about their work, but usually have no way to really make a difference

    Why Do Enterprise Applications Suck?


    images.jpg I consider myself an alpha-geek. I think I have met quite some other alpha-geeks.

    I tend to think that there is hardly any other group of professionals that care so much for their profession like alpha-geeks.

    Regarding passion, dedication and motivation alpha-geeks are very similar to artists or master craftsmen.

    Alpha-geeks usually don't (want to) make a difference between their job and their hobby:
    "Tenet of professionalism: Work 40 hours for your employer and another 20 hours improving yourself." (tweet by unclebobmartin)

    ... at least that would be the case in an ideal world ...

    In reality I have almost never met a passionate developer, that is really happy with his job.

    In reality it's more likely that the alpha-geek is working the additional 20 hours, because he is frustrated with the 40 hours he had to spend for his employer... because he could not realize his ideas of real development, because he was bogged down with fabricated complexity, because he lost his way in a maze of legacy code and because he had to spend so much time and energy for bureaucratic overhead ...

    This is a schizophrenic situation, and I wonder why it is so common?

    cubicle.jpg Probably a lot can be credited to the Office Space clichés that can be found in corporate environments. And to the fact, that in a lot of those environments it's impossible to deliver software that matters.

    But I think it's too easy to lay all the blame on corporate environments.


    I think a part of this schizophrenic situation can be credited to a blame-the-others-syndrome. If things are hard and if there is friction, it's always easier to blame the others. It's only self-protection to assume the stance "If I only could do things my way, everything would be good!"

    I also think software development is especially susceptible to this schizophrenia, because nowadays it almost exclusively deals with intellectual constructs. It is very easy to create a clean, wonderful notion of a perfect software system and to imagine an ideal software development process. That's because we can let our imagination run wild, since there are no real constraints in theory. At least in theory there always exists a perfect solution. That's a major difference to other (real) engineering disciplines.
    It's very convenient to think that we could realize the perfect solution, if only we could do things our way...
    ...only in our perfect solutions we did not consider those accidental constraints like people, time, economic factors ...

    image_thumb.png
    A third aspect is that there are hardly any measurable characteristics in software development. Therefore personal taste, preferences and gut feelings become important. And since these are very individual, it's a logical consequence that we always have to deal with compromises when we are working with other people.


    I believe that leveraging the passion and motivation of developers is a key factor for forming highly productive teams. This has been shown with different studies.
    But to a certain degree this is a blade with two edges. Highly passionate developers are much more susceptible to the schizophrenia mentioned above. I think the key is to accept, that real-world software development is never perfect. Our job is it to pragmatically live with this imperfection.
    Related Posts Plugin for WordPress, Blogger...