<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-390795412396279417</id><updated>2012-02-16T05:04:43.564-08:00</updated><category term='objects'/><category term='PHP'/><category term='unserialization'/><category term='object serialization'/><category term='serialize'/><category term='objects serialization'/><category term='serialize objects'/><title type='text'>Code Temple</title><subtitle type='html'>There are no problems - only challenges!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-390795412396279417.post-4650908572343972561</id><published>2011-12-05T14:50:00.001-08:00</published><updated>2011-12-05T14:52:32.611-08:00</updated><title type='text'>ReflectionException: Method PHPUnit_Framework_Warning::Warning() does not exist</title><content type='html'>If you ever got error like this:&lt;br /&gt;&lt;blockquote class="tr_bq"&gt; &lt;b&gt;ReflectionException: Method PHPUnit_Framework_Warning::Warning() does not exist&lt;/b&gt;&lt;/blockquote&gt;It means you have no tests defined in your unit test file. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/390795412396279417-4650908572343972561?l=codetemple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/4650908572343972561/comments/default' title='Rašyti komentarus'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=390795412396279417&amp;postID=4650908572343972561' title='0 Komentarai (-ų)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/4650908572343972561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/4650908572343972561'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/2011/12/reflectionexception-method.html' title='ReflectionException: Method PHPUnit_Framework_Warning::Warning() does not exist'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-390795412396279417.post-7652009079010338162</id><published>2011-05-10T15:08:00.001-07:00</published><updated>2011-05-11T00:04:26.226-07:00</updated><title type='text'>Thoughts about: PHP - CQRS - Axis2 - Java - Quercus - ES - DDD  - Messaging</title><content type='html'>Year ago I have started to work on a small PHP framework that had a purpose to help me out to implement CQRS based architecture for a pretty large e-commerce system. It took me 4-5 month but I did create first version and went live. Next month it will be one year when CQRS based system implemented only with PHP is live and rolling. And all I can tell you that I was never happier than now.&lt;br /&gt;We are able to manage complexity, we are able to be agile from business perspective, we are able to maintain and develop new features while being a pretty small team. It's awesome, but still now I have started to think about how I could improve all this even more.&lt;br /&gt;&lt;br /&gt;So let's see what we got now and what bothers me.&lt;br /&gt;At very top level our system is based on SOA principle, we are organizing ourselves around services. One specific thing is those services are domain focused services. What we did at the beginning was that we have identified domain models and then we did draw boundaries which actually has formed bounded contexts (Domain Driven Design). For us bounded context is like a sub-system, some specific domain focused system, with a well-defined interface. For example "Sales", "Support" sub-systems/bounded contexts. The most important thing here is - well-defined interface. Because as you understand once you do got an interface, behind it you can have anything you want.&lt;br /&gt;&lt;br /&gt;So we got our BCs. Now inside it we got CQRS based system. Well not all of them got it, but most of them. We got read side with simple "Query" classes designed for our needs. It's simple php classes doing queries to our reporting storage (for some we use mongo, for some MySQL). Then we got our write side. If we would be going from top-to-bottom first of all we got our Application layer. This layer got application services which basically publishes interface what you can do with our domain. This layer got no logic apart how to publish message to some messaging system. So once message is in a bus (we are using RabbitMQ and we are more than happy) on the other end we got X PHP daemons running and consuming those messages. Those daemons are getting messages from messaging system, then it builds a command and executes it. Execution means that we are performing some action on our domain model which again is written in PHP. Our domain processes the request and generates events that represents state changes, those events then are stored to event store (we are using mongo to store events). Lastly event handlers are notified that some events has occurred and thats where we got our reporting updated with data.&lt;br /&gt;We also got event versioning so that our domain model would support only the latest events.&lt;br /&gt;&lt;br /&gt;And all this works perfectly. Everything is decoupled, has its place and simply its very clear what is where, why, how and when.&lt;br /&gt;Gods knows how many times I was saved because of events I got. Generate new reports, analyze events and see why the hell one or another thing happened. Because of CQRS it was easy to split work load and to simplify domain model like N times ? One model - one purpose read or write, simply as that.&lt;br /&gt;&lt;br /&gt;But now  I want to improve all this and was thinking about bit different setup. Concepts, patterns remains as they were it's just technologies that I want to replace.&lt;br /&gt;&lt;br /&gt;First of all - web services. PHP was never meant to be used to create web services. It works, it will do the job for you. I have done that and it is running and partners are using, but it's "weak". I mean what about WS-* ? I found only one project that is trying to implement these specifications WSO/Oxygen Tank. But when I did try it, it was hard to use and simple not working. Also for all such tasks you need tools to make your life easier while developing, deploying. So I thought this is where I will draw a line and I will try to replace it with something else. And my first candidate was Axis2 Java implementation. We got WS-*, we can create and deploy web services very easily and fast and features like "hot deployment" really helps you a lot. Also it's proven and tested technology.&lt;br /&gt;So then I thought what if as SOAP engine I would use Axis2 and application layer would be implemented in Java as well. It is a thin layer with no logic just simple messages publishing mechanism. And then at the other end I would have everything as it is now - PHP domain implementation.&lt;br /&gt;In addition to that I have added quercus to this stack. Its PHP implemented in Java. And this allows me to create a front-end with a language that is most suited for it. And because it is implemented in Java I am getting all Java abilities.&lt;br /&gt;&lt;br /&gt;One last thing. To answer a question why PHP ? It's simple as that - its easy to find developers, PHP developers are cheaper, simply why not ? Tell me one good reason why startup company shouldn't be using PHP as back-end language ? An besides if you will need to replace it with Java, Scala, .NET or with anything else - who will stop you ? It's all about "who" will be consuming messages, no?&lt;br /&gt;&lt;br /&gt;So, this is what I am thinking at the moment. Any comments are more than welcome ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/390795412396279417-7652009079010338162?l=codetemple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/7652009079010338162/comments/default' title='Rašyti komentarus'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=390795412396279417&amp;postID=7652009079010338162' title='0 Komentarai (-ų)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/7652009079010338162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/7652009079010338162'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/2011/05/thoughts-about-php-cqrs-axis2-java.html' title='Thoughts about: PHP - CQRS - Axis2 - Java - Quercus - ES - DDD  - Messaging'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-390795412396279417.post-7895990796592791273</id><published>2010-07-17T15:38:00.000-07:00</published><updated>2010-07-17T16:23:00.401-07:00</updated><title type='text'>DDD - too large Agregate root</title><content type='html'>Last week, while I was working on some code for my current project at work I ran into problem where my aggregate root had too many child entities, way too many. My aggregate root snapshot was about 20 MB and that of course gave me a sign that it is wrong.&lt;br /&gt;&lt;br /&gt;Model was rather simple one. I had to create a model for voucher system. Every deal that our company creates would need about 100k vouchers. Every deal has vouchers that provides different so called gifts to customers. And those deals are created pretty often, so we are talking about millions of vouchers.&lt;br /&gt;&lt;br /&gt;Now voucher was identified as entity because it has behaviors. And as an aggregate for them I have presented Stock entity. It hold references to all vouchers and those were accessible through it. Also it was responsible for generating vouchers and exporting them. I was using a rule that there always should be a higher 'thing' for my entities and that thing should know what entities exists out there. It's like for licenses we have stock, for invoices ledger and so on.&lt;br /&gt;Now why it is wrong ? (Well I think it is wrong)&lt;br /&gt;&lt;br /&gt;First of all in this way I am transferring repository responsibility to other object - stock, ledger etc. I am creating repository that holds all data in-memory while I do not need it. What I really need is just another domain service.&lt;br /&gt;So, let me explain how I have re-modeled my domain here.&lt;br /&gt;&lt;br /&gt;Stock aggregate root remains but voucher becomes an aggregate root. I do present new aggregate root - VoucherGenerator that has knowledge about voucher code generation strategies. And what I do to solve problem is I add new services like GenerateVouchersService, VoucherLookupService. Instead of having behavior on stock 'GenerateVouchers' i move this to Generator AR and then use this in service GenerateVouchersService to actually create new vouchers and add those to repository.&lt;br /&gt;In this was my repository does what it suppose to do - acts as in-memory domain objects collection and my domain entity becomes free of millions child entities. Of course it still has a map of voucher code - UUID in my stock aggregate and I use it to get voucher UUID that later is used to get entity from repository.&lt;br /&gt;&lt;br /&gt;Of course Stock AR still will have lot of data in it, but what we can do is introduce 'ClearOldVouchers' behavior. Or remove voucher once it was used. And if at some point later I will have to restore my entities, because of event sourcing I am still able to do that.&lt;br /&gt;&lt;br /&gt;So as you see, in this way we have solved large-aggregate-root problem and at the moment it seems to be the best solution for me.&lt;br /&gt;&lt;br /&gt;Any comments ? Have you any other solution ?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/390795412396279417-7895990796592791273?l=codetemple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/7895990796592791273/comments/default' title='Rašyti komentarus'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=390795412396279417&amp;postID=7895990796592791273' title='0 Komentarai (-ų)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/7895990796592791273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/7895990796592791273'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/2010/07/ddd-too-large-agregate-root.html' title='DDD - too large Agregate root'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-390795412396279417.post-6693009251470024223</id><published>2010-03-06T14:43:00.000-08:00</published><updated>2010-03-06T15:35:24.738-08:00</updated><title type='text'>Applying Scrum - Sprint Planning - Mind Map</title><content type='html'>Last Thursday our team have finished 3rd sprint. Despite some issues, we have achieved our goal and on Monday we will have our demo. &lt;br /&gt;&lt;br /&gt;This evening I was sitting here and was analyzing how we were progressing during sprint. One new thing that we have tried for this sprint was - 'no story splitting into tasks' thing. What we did was, that we just created few tasks for the first day of the sprint and agreed to create the other tasks on the fly, whenever we will need it during sprint. After that we just brainstormed about all sprint stories and what solutions we can suggest for product owner.&lt;br /&gt;&lt;br /&gt;So now when I am looking back to how it worked, I really like it. First of all sprint planing meeting was not so 'hard'. We were just sitting and discussing things. And if I try to compare it with sprint planning that happened before this one, so I could say that last one was much more productive. Because we were not forced to commit ourselves on what exactly we will have to do and how long it will take, like 'create x files' and 'create y things' and so on. But instead we analyzed in general how we will do it and what the best solution we can offer to our product owner. I think we have covered more things in this way compared to the splitting-into-concrete-tasks way.&lt;br /&gt;&lt;br /&gt;Now during sprint, in every daily scrum we have defined new required tasks and agreed who will work on each task. What I liked the most about all this was that it was so easy to create those tasks. It was very clear what we need to do. Every morning there were new challenges that we had to take if we wanted to achieve our goals. And now when I have putted all those sprint tasks on the wall and joined them, I noticed that I have got a web:&lt;br /&gt;&lt;br /&gt;Story A -&gt; task 1 -&gt; task 2&lt;br /&gt;           task 1 -&gt; task 3&lt;br /&gt;           ....&lt;br /&gt;&lt;br /&gt;And that gave me an idea.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_L1G9rmj2y7Y/S5LmjWrJTwI/AAAAAAAAABI/2cqCseo4b4M/s1600-h/mindmap.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 200px; height: 120px;" src="http://3.bp.blogspot.com/_L1G9rmj2y7Y/S5LmjWrJTwI/AAAAAAAAABI/2cqCseo4b4M/s200/mindmap.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5445668394500706050" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This sprint we will do the same thing, just I will try one additional activity. I will try in next sprint planning meeting to use a mind map tool. While we will brainstorm about each story, I will time-box each session for 10-15 minutes and will see with what trees we will come up. Then I will print all those trees and during daily scrum we will use those to define tasks. &lt;br /&gt;What I hope to achieve is - better solution. Because during brainstorm session, of course we will define some solution for a story, but first solution, at the most of times, is the one that will be re-factored. So I hope these mind-maps will have those first solutions and during sprint, in daily scrums, we will see what solutions we already have and perhaps we will define some new ones and better ones and in this way we will improve quality of our software. &lt;br /&gt;&lt;br /&gt;Let's see if it works.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/390795412396279417-6693009251470024223?l=codetemple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/6693009251470024223/comments/default' title='Rašyti komentarus'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=390795412396279417&amp;postID=6693009251470024223' title='1 Komentarai (-ų)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/6693009251470024223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/6693009251470024223'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/2010/03/applying-scrum-sprint-planning-mind-map.html' title='Applying Scrum - Sprint Planning - Mind Map'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_L1G9rmj2y7Y/S5LmjWrJTwI/AAAAAAAAABI/2cqCseo4b4M/s72-c/mindmap.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-390795412396279417.post-8072816936709377628</id><published>2010-03-02T13:24:00.001-08:00</published><updated>2010-03-02T13:34:35.755-08:00</updated><title type='text'>Convert problems to challenges</title><content type='html'>We had sprint planning meeting and it was really hard meeting. Lot of unknown things about stories and problems were there and there and it seemed that all this product is one big problem. So what our product owner suggested, was like this (credit goes to Charlotte Way):&lt;br /&gt;&lt;blockquote&gt;Let's change the word problem to challenge and when you have a problem, instead of saying I have a problem, say I have a challenge.&lt;br /&gt;&lt;/blockquote&gt;And you know it really works. It was not so depressive anymore to talk about those problems, because there were no problems! Product now is a challenge and bad 3rd party API is a challenge, that bug is a challenge and when you get used to that word it really works, and everything looks much easier.&lt;br /&gt;&lt;br /&gt;So from that day, I do not have any more problems, there are only challenges!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/390795412396279417-8072816936709377628?l=codetemple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/8072816936709377628/comments/default' title='Rašyti komentarus'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=390795412396279417&amp;postID=8072816936709377628' title='0 Komentarai (-ų)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/8072816936709377628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/8072816936709377628'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/2010/03/convert-problems-to-challenges.html' title='Convert problems to challenges'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-390795412396279417.post-7578024483188979500</id><published>2010-03-02T12:11:00.000-08:00</published><updated>2010-03-02T13:23:38.988-08:00</updated><title type='text'>Applying Scrum - Part 1</title><content type='html'>Few weeks ago I read a book, which basically was about how practically scrum was applied in one big company. Good thing about that book was that it contained only practical examples how Scrum worked for them, no theory, only pure practical examples.&lt;br /&gt;That book helped me a lot, so I thought perhaps it would be good idea to share how we do scrum and perhaps someone will find it useful.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;It's about team members &lt;/span&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;commitment &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Challenge &lt;/span&gt;- make team feel responsible for a product&lt;br /&gt;&lt;br /&gt;At the beginning, when I have started to implement Scrum, everything was pretty ok. We have implemented all those basic scrum rules like daily scrum, we had backlog, product owner, scrum master, agreed on sprint length and so on. But despite of lot of other challenges, I will cover those later, after few sprints we were failing to deliver what we have promised and deliverables was note actually DONE.&lt;br /&gt;So I was thinking were is that challenge? why this team is failing ?&lt;br /&gt;When I have started to analyze, what actually we were doing during sprint, I found that team was not working as a team, but they rather just waited till what I will say how and what we should do! Daily scrum was like "so what should I do now ? I did that, and that, what next ?" And when you fall into this, when you start thinking what all should do, you are starting actually to manage them and that is wrong very wrong.&lt;br /&gt;Team must feel responsible for what they are delivering. You have a goal and you are responsible to do everything what you can to achieve that goal, there is always something you can do, you just have to feel that this is your product and you will see that there is a thousands of tasks that you can start working on. And there should be no "you" and "me", there must be a team and everyone must understand that if I will fail to do something - all team will fail.&lt;br /&gt;And what happens when there is one person who is creating and assigning tasks and he is the only one who sees the whole picture? You always can blame him and only that person will be responsible.&lt;br /&gt;&lt;br /&gt;So, lesson that I have learned is:&lt;br /&gt;&lt;blockquote&gt;Before you start sprinting, make sure that team understands what that word "team" really means. Try to make them feel that they are a part of something that they are about to create. And also  explain people what each of team member is and should be expecting from each other - that would be &lt;span style="font-weight: bold;"&gt;responsibility.&lt;/span&gt;&lt;/blockquote&gt;I think that if you want to be a very very productive team, first of all, all team members must feel responsible for the product and treat it like it would be their own baby.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/390795412396279417-7578024483188979500?l=codetemple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/7578024483188979500/comments/default' title='Rašyti komentarus'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=390795412396279417&amp;postID=7578024483188979500' title='0 Komentarai (-ų)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/7578024483188979500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/7578024483188979500'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/2010/03/applying-scrum-part-1.html' title='Applying Scrum - Part 1'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-390795412396279417.post-6705671873763589332</id><published>2010-02-28T14:48:00.000-08:00</published><updated>2010-03-01T07:36:55.277-08:00</updated><title type='text'>DDD/CQRS/Event sourcing and Agile/Scrum - Is it so obvious?</title><content type='html'>I was sitting here and was creating a roadmap for a system that I am currently working on. Nothing special, but still, it's big eShop system with big backend system and has lot of integrations with 3rd party systems and has complex business rules and so on.&lt;br /&gt;Anyway, now why I am writing this, is because I think that all who are reading about CQRS, Event sourcing, Agile, Scrum etc., should be interested in it. Perhaps all top guys like Greg Young, Udi Dahan and lot of others knows that, but I have tried to ask google and got zero results on what I am about to write.&lt;br /&gt;Or perhaps it's so obvious that no one is writing about it? let's see&lt;br /&gt;&lt;br /&gt;I will not go into details what is Scrum and Agile and CQRS and Event sourcing, I assume that you know what it is, and instead of that I will share my thoughts on how all these 'things' works together and what a great value it can bring to you.&lt;br /&gt;&lt;br /&gt;So, first of all some preconditions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;My team works in Scrum environment (we pass NOKIA test)&lt;/li&gt;&lt;li&gt;We have applied CQRS architecture along with Event sourcing &lt;/li&gt;&lt;li&gt;We use DDD&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Now, as I was saying,  because I am ScrumMaster, so I was helping our Product Owner  to create a roadmap for our current project. We have a loads of work/features to implement and also there is a very big pressure from stakeholders to go live as soon as possible. There is along story why we need go live as soon as possible, but thing is that we must, otherwise business will suffer a lot. So  puzzle is something like this:&lt;br /&gt;- You have to deliver X features till Y date, but to develop those X features with quality there is no way you can do it till Y date. So what to do ?&lt;br /&gt;&lt;br /&gt;So I was splitting stories and batching them and preparing them for Product Owner that she  could prioritize those and then I have realized:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;What you gain from CQRS? You have &lt;span style="font-weight: bold;"&gt;write only&lt;/span&gt; domain (there are of course more, but this is  the most important for this article)&lt;/li&gt;&lt;li&gt;What you gain from event sourcing ? You have a full &lt;span style="font-weight: bold;"&gt;audit &lt;/span&gt;of your system. You know every single step that was made on your system, I mean every.&lt;/li&gt;&lt;li&gt;How product is build in Agile environment? You do it step by step, creating tested and shippable &lt;span style="font-weight: bold;"&gt;increments&lt;/span&gt; that at the end of the day builds up a product&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;So, I think some of  you are getting the picture already. Now if we have a really good user stories, our stories are written in INVEST way, so we can create &lt;span style="font-weight: bold;"&gt;the most important related features/stories&lt;/span&gt; in first sprints and if that is enough for business - we can go live. Yes, that is right, go live. Deploy system to production environment, start promoting and do all the rest that business needs.&lt;br /&gt;Meanwhile Scrum team will start implementing &lt;span style="font-weight: bold;"&gt;future features,&lt;/span&gt; that are related to our deployed features and requires generated data from them. And thing is that once we are done with our so called &lt;span style="font-weight: bold;"&gt;future features,&lt;/span&gt; we can take out event log from our production environment, plug it in to our staging environment, click 'replay' button and wait till our data, generated in production environment, will be grabbed by newly implemented features. Those features then will update their state (internal event handlers), update required storages (external event handlers) etc. And once it done, we can go live again, but this time our system will have newly implemented features, and moreover, it will look like those features were there from the beginning!&lt;br /&gt;For example we need reporting functionality for sales department (we call it bounded context, because its separate, autonomous mini application) that says how many sales were done and so on. So once we have reporting features implemented we can replay events (sales events) that happened on production environment and let '&lt;span style="font-weight: bold;"&gt;reporting features&lt;/span&gt;' do what they suppose to do when that kind of event occurs! Isn't it amazing ? You can create &lt;span style="font-style: italic;"&gt;future &lt;/span&gt;while &lt;span style="font-style: italic;"&gt;present &lt;/span&gt;is running, gathering data and then integrate all this and put it back for  production usage, like it was there from the beginning! (I am repeating myself i guess :))&lt;br /&gt;&lt;br /&gt;Of course, I hear you saying that there are features that can not be plugged in  like that, and I totally agree with you, but perhaps it means then that those must go together in one sprint, or must be rethought if those, related features, are really important to business and must be included in sprint. Because at the end of the day, its all about business and what value one or other feature will create.&lt;br /&gt;&lt;br /&gt;So, that would be it. I hope it will help someone. I really would like to get some feedback on this, so if you have something to say about this, you are more then welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/390795412396279417-6705671873763589332?l=codetemple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/6705671873763589332/comments/default' title='Rašyti komentarus'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=390795412396279417&amp;postID=6705671873763589332' title='2 Komentarai (-ų)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/6705671873763589332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/6705671873763589332'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/2010/02/dddcqrsevent-sourcing-and-agilescrum-is.html' title='DDD/CQRS/Event sourcing and Agile/Scrum - Is it so obvious?'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-390795412396279417.post-5159794150355211355</id><published>2009-08-24T20:35:00.000-07:00</published><updated>2009-08-24T20:50:50.952-07:00</updated><title type='text'>Zend Framework poster</title><content type='html'>Few weeks ago my friend showed me a very nice ZF poster that Germany company, called "&lt;a href="http://www.mayflower.de/"&gt;Mayflower&lt;/a&gt;" is spreading around the world for free, just because they likes Zend Framework.&lt;br /&gt;So, i also asked for one, and here it is:&lt;span class="gI"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_L1G9rmj2y7Y/SpNdQ1wia8I/AAAAAAAAAAc/hbgBvUy9rdY/s1600-h/IMG_0718.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/_L1G9rmj2y7Y/SpNdQ1wia8I/AAAAAAAAAAc/hbgBvUy9rdY/s400/IMG_0718.jpg" alt="" id="BLOGGER_PHOTO_ID_5373741324273085378" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you want one, just write a short email with asking for one to &lt;span style="font-weight: bold; font-style: italic;" class="gI"&gt;&lt;a href="mailto:bjoern.schotte@mayflower.de"&gt;bjoern.schotte@mayflower.de&lt;/a&gt; &lt;/span&gt;&lt;span class="gI"&gt;and in few weeks you will have your poster.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It is very nice to see that there are such companies as "&lt;a href="http://www.mayflower.de/"&gt;Mayflower&lt;/a&gt;", which are not just using this wonderful framework, but also makes such things to inform people that there is such framework and that you definitely should have a look in it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/390795412396279417-5159794150355211355?l=codetemple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/5159794150355211355/comments/default' title='Rašyti komentarus'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=390795412396279417&amp;postID=5159794150355211355' title='2 Komentarai (-ų)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/5159794150355211355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/5159794150355211355'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/2009/08/zend-framework-poster.html' title='Zend Framework poster'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_L1G9rmj2y7Y/SpNdQ1wia8I/AAAAAAAAAAc/hbgBvUy9rdY/s72-c/IMG_0718.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-390795412396279417.post-7132743399565168575</id><published>2009-01-09T06:54:00.000-08:00</published><updated>2009-01-09T14:42:26.685-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unserialization'/><category scheme='http://www.blogger.com/atom/ns#' term='serialize'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='object serialization'/><category scheme='http://www.blogger.com/atom/ns#' term='objects'/><category scheme='http://www.blogger.com/atom/ns#' term='serialize objects'/><category scheme='http://www.blogger.com/atom/ns#' term='objects serialization'/><title type='text'>PHP objects serialization</title><content type='html'>This week I was working on developing two systems integration mechanism. Integration was based on XmlRpc web services. After a successful web services framework development I have started to implement businesses logic and stuck on objects serialization.&lt;br /&gt;&lt;br /&gt;When I tested serialization of simple objects, that had only few methods and no properties, everything was working just fine. I serialized object on one system, send to remote one and unserialized for usage. But when I have added properties to object, the remote php web service was not able to unserialize received object. It took me some time to find out that those private properties and was the real problem. Because of unknown reason private and protected properties are not handled nicely in serialization process private variables are prefixed with class name + #65533; and protected with #65533;. Anyway the fix was to encode serialized string to base64 and on remote side before unserialization decode from base64.&lt;br /&gt;For example:&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;class LeetObject&lt;br /&gt;{&lt;br /&gt;      private $property;&lt;br /&gt;      protected $_property;&lt;br /&gt;&lt;br /&gt;      public function test()&lt;br /&gt;     {&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;$obj_category = new LeetObject();&lt;br /&gt;$b64_encoded_and_serialized = base64_encode(serialize($obj_category));&lt;br /&gt;&lt;br /&gt;// Send somewhere&lt;br /&gt;// And on remote system&lt;br /&gt;&lt;br /&gt;$obj_category = unserialize(base64_decode($obj_category));&lt;br /&gt;&lt;br /&gt;// Use object&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;Hope this will help someone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/390795412396279417-7132743399565168575?l=codetemple.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codetemple.blogspot.com/feeds/7132743399565168575/comments/default' title='Rašyti komentarus'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=390795412396279417&amp;postID=7132743399565168575' title='0 Komentarai (-ų)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/7132743399565168575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/390795412396279417/posts/default/7132743399565168575'/><link rel='alternate' type='text/html' href='http://codetemple.blogspot.com/2009/01/php-objects-serialization.html' title='PHP objects serialization'/><author><name>Tomas Bartkus</name><uri>https://profiles.google.com/104536080336551140484</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-Tj1J3TBQh-M/AAAAAAAAAAI/AAAAAAAAACg/Dtcw0e7eGcE/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
