сряда, 15 декември 2010 г.

TDD Antipatterns

This time I just want to link to something really rich I encountered - a catalogue of TDD antipatterns.

It really relates to my current work on a legacy system, where a lot of tests exhibit "The Liar" and "The Greedy Catcher". This way, even a successful run of the full suite (which happens quite rarely) gives you a sense of false safety.

събота, 25 септември 2010 г.

It's surprising how simple concepts could evade one's mind for incredible amounts of time. I'd never explained to myself fully what a static class or interface means. Never took the time to read about it.

сряда, 1 септември 2010 г.

Open-source and code-quality

Over the past few months, at the Eclipse demo camp in Sofia first, I've been hearing about the Virgo server,
part of the EclipseRT project.
Although the main current usecase of Virgo is deploying and running JEE Web modules and Spring apps, in its core it is just an OSGi runtime. This means that it can be distributed without the Tomcat servlet container, and since it has the OSGi modularity, you can potentially create different 'servers' out of it to suit your needs,  provided you deploy the bundles you need for the job.
To be honest, I haven't given it a try yet. The reason I am writing this is that last night I took a quick glimpse of the source code of the kernel, and... Well, first-looks show the code is really high-quality. It leaves you with the impression that if you check it out, you can start working with it immediately, having little to no knowledge of the domain area. To a person with no knowledge in the product, stuff seems cleanly designed, hidden behind interfaces, documented, unit and integration tested, so forth. I don't think I encountered a class > 500 LOC, which was quite a pleasant surprise.
The only thing that really puzzled me and turned me off a bit :) "The use of the 'final' qualifier on method parameters and local variables is strongly discouraged. " (from the product's code convention) Ah well. Question of taste...
Anyways, at a first glimpse, at least the internal quality of this product seems to showcase what open-source can achieve. (Well, it's been open-source for some time now, the initial contribution was made by SpringSource, so kudos you guys).

You can take a look what is being planned for the product here. If you are interested to know about the Virgo community, or interested to become a contributer, check this out.

I'll take the time to take her for a spin as soon as I get some school work off my back this week...
With relation to one of my previous blogs (in Bulgarian), one should be able to use Virgo as a nice RAP runtime, if they deployed the RAP platform bundles on Virgo. No servlet bridge or stuff.

неделя, 29 август 2010 г.

UnsupportedOperationException controversy

In my view, some controversy can be seen concerning the existence of the UnsupportedOperationException class.
The LSP, one of the SOLID principles of object-oriented designs, suggests that correct OO systems should exhibit behavioural subtyping. This informally means that replacing occurences of e.g. Dog objects inside your program with e.g. Pitbull objects should result in your program functioning the way it did before, provided Pitbull is a subtype of Dog.
If a Dog class correctly implements the bark() method, and Pitbull throws an UnsupportedOperationException in its bark() method, behavioural subtyping is no longer the case. Clients of Dog relied it is perfectly safe to invoke its bark() method, and replacing occurences of Dog with Pitbull will make client code fail everywhere the method in question is being invoked.
Such an OO system obviously exhibits bad design. When the behavioural is-a relationship between parent and child class is broken, polymorphism cannot be utilized to its full power.

An extreme opinion can be stated that the very existence of UnsupportedOperationException gives the tool for junior programmers to violate the LSP.

So why does UnsupportedOperationException exist in the first place, and what is its correct usage?

Good insight can be gained by studying what the Java Collection Framework designers have to say. They chose to create fairly generic interfaces with optional operations instead of a large set of specific intefaces, to circumvent two problems:

- There could be interfaces for lots of specific stuff - modifiability, mutability, etc. Combining each new Interface (concept) with the already existing ones creates twice as much artifacts in the hieararchy. It also creates a parallel hierarchy, which is an OO antipattern (ModifiableLinkedList on the one side, ImmodifiableLinkedList at the other). Repeating the process e.g. a second time makes, it the worst case, four times more artifacts and two parralel hierarches each consisting of a set of two parralel hierarchies in their turn. Ultimately the size of the hierarchy blows up exponentially. Needless to say, implementing code reuse through the parallel branches becomes a major pain in the ass, since Java has no multiple inheritance. You will have to introduce delegation to circumvent this, but when you add one more concept to the framework, you will again end up with a parallel hierarchy in the delegate objects, and you will need one more layer of delegation to circumvent the problem again. Such design soon becomes unmanageable, even for simple enough domain areas.
- There was no way to envision all the sets of concepts (interfaces) that will have to be introduced to suit all possible real-world Collection implementers.

So the approach of generic interfaces with optional operations was selected. Implementors to which a certain method was not relevant, would throw an UnsupportedOperationException.
Such an approach possibly violates the Interface Segregation Principle on the provider side, but it is a compromise against an exponential size of the hierarchy. In OO Design, one always needs to compromise - this is the tricky part of it.

To sum up, it is permissible in some cases to use the UnsupportedOperationException, to signal that a certain method in the interface is not relevant for an implementation in question. However, throwing this exception in a method which is correctly implemented in the parent class, is always a mistake and a marker of bad design, and must be avoided. Strengthening the throws clause of a child ( @sigals UnsupportedOperationException if(true) ) is a violation of the LSP and hinders use of polymorphism.

The described above child classes most likely realize the more general (anti)-pattern of implementation inheritance. This means they do not have a easily reasonable is-a relationship with the parent class, but rather extend it to reuse some of its code. Implementation inheritance is almost always a bad phenomenon , signalling that the domain was not object-modeled in the best way possible. Implementation inheritance has fallen out of favor for the same reason UnsupportedOperationException can be considered controversial - polymorphism cannot be safely used in such cases.

понеделник, 21 юни 2010 г.

Кратък поглед върху Rich Ajax Platform

Първо прочетете това :)
Тази статия
е прекалено кратка и няма за цел да запознава читателя с Eclipse Plug-in Development или Rich Client Platform Development. Предполагат се общи познания по Eclipse и Eclipse разработка. http://www.eclipse.org/articles и http://www.vogella.de/articles/Eclipse са две добри места за "входна точка" в Eclipse. Започнете първо с навлизане в Eclipse откъм потребителска гледна точка, после се запознайте с архитектурната концепция на платформата, след което можете да се ориентирате към Plugin Development и RCP development спецификите. Ако вече сте направили това, тази статия ще ви даде непретенциозно въведение в RАP.

Web Application Development + Java ?
Изглежда, че към днешна дата, по-големият процент Java програмисти, включително опитните такива, не са способни да разработят Web-базирано приложение, било то богато, или не. Аз самия се вписвам в този процент. Причината е
, че този тип работа изисква специфични познания - в миналото HTML, а сега - JavaScript, CSS, Flash, ... Въпросните Java програмисти пък нямат огромно желание да учат тези технологии,  и така продължават да странят от света на Уеб приложенията. Това е проблем за софтуерната индустрия - голямо количество програмисти, част от които доста способни, не могат да бъдат оползотворени да работят точно по това, което най-много се харчи в днешно време - Web Frontend-ове. От друга страна е много трудно да си намерим качествен Web Developer - такъв, който е едновременно добър софтуерен инженер, и владее добре въпросния спектър от технологии.

Един наш шанс за Ajax в Java света, или по-точно Java EE света, е JSF. Това обаче, поне откъм начин на писане на кода, не е чиста Java технология, и отново създава бездна между Java програмирането и Web разработката. Разбира се, JSF има и големи плюсове, които няма да обсъждаме тук.

Като говорим за RIA разработка на чиста Java, първото за което всички сме дочули и се сещаме е GWT. Вече се появяват и server-side Java технологии за RIA разработка, използващи  GWT за рендериране на страницата при клиента. Така или иначе, вече се налага схващането, че е полезно да можем да пишем уеб приложения на чиста Java.

Какво ви трябва, за да пишете за RAP...
Средата е невзискателна. Всякакъв Servlet Container (напр. Tomcat 6 инсталация), и Eclipse дистрибуция, на която да си инсталирате RAP инструментариум. След малко ще научим , че разработката на RAP приложения е много подобна на RCP/Plugin Development, следователно ще са ви нужни нещата от PDE (Plugin Development Environment) дистрибуцията. Силно препоръчително е да позлвате най-новата версия на Eclipse - за момента Galileo, след две седмици ще излезе Helios. RAP инструментариума се инсталира от този Updatesite.
За да се компилират вашите RAP приложения, ви е нужна RAP target platform-а - как се инсталира тя пише тук.
RAP инструментариума предлага вграден Web Server (Jetty), така че Tomcat не ви е нужен задължително. В случай, че ползвате Jetty, или друга OSGi-базирана разработка, например DMServer/Virgo, Felix, ще можете да се възползвате от много добра интеграция с еклипс, и лесен build/deployment. В противен случай ще ви се наложи да пакетирате приложението си в WAR архив и да използвате така наречения OSGi Servlet Bridge, за да пуснете OSGi фреймуърк в сървъра, който ползвате.

Какво е RAP
RAP е платформа за разработка на RIA, емулираща RCP в уеб среда.
Тази картинка ще видите на http://eclipse.org/rap/introduction.php, както и на всяка презентация/статия, въвеждаща в темата:

Основната цел на RAP е да позволи разработка на богати интернет приложения, преизползвайки Eclipse / RCP програмния модел. Така, на теория, един Eclipse разработчик може веднага да почне да пише Уеб приложения за RАP, без нужда от допълнително обучение.

Основните разлики са две - вместо SWT (Standard Widget Toolkit) - Eclipse-ката Native UI библиотека, се използва RWT (RAP Widget Toolkit). RWT на свой ред, вместо викания към операционната система, прави викания към Servlet контейнера, в който работи, който на свой ред обслужва клиента - уеб браузър, поддържащ JavaScript.

Нека да налегнем че RAP е платформа за писане на проложения, а не на уеб сайтове. С преизползването на RCP модела могат с не много код да се имплементират бизнес приложения, поддържащи задачи, които са свързани с комплексна интеракция с потребителя. 

Пример за такова приложение е http://ondemand.yoxos.com/geteclipse/start. Инструмента позволява да си свалим "тунингована" по наша преценка Eclipse дистрибуция, с всички нужни ни функционалнисти, като има филриране по операционни системи, Plugin/Feature Dependencies се установяват автоматично, има възможност за запазване на Download шаблони, и така нататък.  

За какво можем, и за какво - не бива, да използваме RAP
Тук ще скицираме кратки критерии, които можете да 'огледате' преди да направите архитектурния избор да ползвате RAP за вашето RIA приложение.

- Да показваме по структуриран начин различни набори информация/артефакти, живеещи на мрежата
- Да управляваме комплексни взаимодействия с потребителя
- Да изпълняваме бавни операции асинхронно, запазвайки responsiveness на интерфейса
- Да имплементираме WYSIWYG редактор...

Ако голяма част от изброените функционалности не съществуват като изисквания към приложението ни, RAP може би не е добър избор.
Например - 
- Ако информацията, която обработваме е чист текст, който няма нужда да бъде структуриран.
- Ако само визуализираме артефакти в приложението си, но не се налага да се редактират.
- Ако взаимодействията ни с потребителя не са сложни

-Ако пишем сайт - бил то и такъв, в който се споделя съдържание
- Ако не се изисква висока responsiveness на интерфейса - тогава трябва да се запитаме, нужен ли ни е Ajax фреймуърк изобщо.

Разширяемост  и управление на жизнения цикъл
Ако вашето богато уеб проложение има изискване за разширяемост (лесно добавяне на нова функционалност) и обширна конфигурация (промяна на начина, по който работи съществуващата такава), RAP може да се окаже много добър избор на платформа. Тези две функционалности идват наготово от еклипс програмния модел - а именно plugin компонентния модел и runtime модела - OSGi.
Новата функционалност, която сме внедрили, на практика би представлявала просто един нов plugin във Equinox(OSGi) инстанцията, в която върви приложението. Това означава, че при добри условия, крайния потребител ще я види, след като рестартира браузър сесията си.
Бихме могли и да напишем функционалност, която е абстрахирана от конкретните начини, по които ще бъде разширявана, четейки от Extension Registry имплементации на добре дефинирани Java интерфейси.
Обновяването на съществъваща функционалност също може да мине напълно безболезнено за цялото приложение, стига въпросната нова промяна да не е счупваща за останалия свят, и Plugin-ите които зависят на функционалността, да са толерантни към промяна на малките сегменти на версията.

Основни потребителски сценарии на RAP
Основният сценарий, заради който е разработена RAP платформата, се нарича Single-Sourcing. Целта е да може от една и съща код база да се създават богати клиентски и уеб приложения. (RAP & RCP) На практика ще има известна разлика между крайните версии на двете кодбази, но тя ще е доста ограничена, а и съществуват техники да се управлява лесно, както е подробно обяснено в прикачената към библиографията книга.
Single-sourcing техниката може да бъде използвана, когато искаме да таргетираме по-голяма клиентска група с приложението си, когато искаме да и осигурим по-всеобхватен достъп към него, или пък защото сме в начален стадий на разработка и не желаем все още да вземем решение, дали ще продаваме приложението си като "дебел клиент" или уеб клиент.

Друг сценарий би бил мигриране на съществуващо клиентско приложение към Уеб среда. Представете си например даден мейл клиент, който се използва в корпорация X като десктоп приложение. Всеки update на клиента,който трябва да се наложи на всички машини в корпоративната мрежа, е скъпо, времеемко и сложно занимание. С мигриране към Wеb интерфейс напълно се губи нуждата от такава процедура, тъй като софтуера се обновява само на едно място - на приложния сървър.
Обикновено е възможно да се мигрират съществуващи Eclipse/RCP приложения към RAP без голямо усилие. Статистически около 75% от кодбазата не се нуждае от никаква модификация.
Въпросното мигриране е добре изследвана територия, и е описано в книгата, спомената в библиографията долу. Сериозни проблеми бихме имали с приложения, които разчитат много силно на наличието на локална файлова система, работейки с org.eclipse.core.resources интерфейса.

Не на последно място, съществува и сценария, в който бихме желали да изградим чисто ново WEB приложение с RAP, защото сме решили че платформата е подходяща за задачата.

Ограничения на RAP
Тъй като до сега бяхме изцяло оптимистични, е добре да споменем няколко ограничения на RAP с цел "управляване на очакванията".

- Неразполагането с операционна система, към която да се обърнем, ни лишава от някои възможности, които бихме очаквали в RCP. Например, не можем свободно да рисуваме произволни наши форми върху интерфейса. (Това може да се промени в близко бъдеще с навлизането на HTML 5 Canvas)- Разпределеният характер на мрежовите приложения, латентността в мрежовата инфраструктура, и изискванията за скалируемост на цялото уеб приложение, налагат промени и рестрикции върху RCP програмния модел. Както се вижда от архитектурната картинка, тези промени са основно в RWT API-то спрямо SWT
- Участниците в RAP проекта са работили доста върху скалируемостта на платформата. Въпреки това не е добра идея да се използва RAP за имплементиране на тежка бизнес логика, защото приложението, за разлика от RCP света, може да бъде достъпвано от мног клиенти едновременно. Добре е подобна логика да се изнася в бизнес компоненти, които могат да скалират добре, например EJB, и RAP да се ползва за презентационен слой и "леки" обработки на данни, с цел показване в интерфейса, и подаване обратно на бизнес логиката.

1. http://www.eclipse.org/articles
2. http://help.eclipse.org/ 
3. http://www.eclipse.org/rap
4. Eclipse Rich Ajax Platform - bringing Rich Clients to the Web - Fabian Lange.