<?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-898376252540041162</id><updated>2012-02-17T03:03:58.988+02:00</updated><category term='linux'/><category term='Tech Talks'/><category term='python'/><category term='python3k'/><category term='sweet wtf'/><category term='unit testing'/><category term='tdd'/><category term='Caching'/><category term='Configuration Files'/><category term='bash'/><category term='mockito'/><category term='lessons learned'/><category term='distribute'/><title type='text'>Serhiy Oplakanets</title><subtitle type='html'>Title under construction. Send your ideas directly to trash can - I won't like it anyway.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Serhiy Oplakanets</name><uri>http://www.blogger.com/profile/03228323520185072155</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-898376252540041162.post-6806199972369917714</id><published>2010-10-07T00:54:00.006+03:00</published><updated>2010-11-06T15:25:55.346+02:00</updated><title type='text'>Mess is just a mess</title><content type='html'>&lt;p&gt;People tend to call mess a "challenge". That is seriously wrong in my opinion. Imagine you wake up after a party in your house &amp;mdash; empty bottles everywhere, pizza boxes glued to ceiling, etcetera etcetera. Looking at all of this, what will you say? Will you ever say "what a challenge"? Well, if you will, you should consider visiting a doctor. "What a mess" a mentally healthy person would most probably say. So why would you call, say, thousand lines spaghetti code a "challenge"?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Mess is just a mess. Call it whatever you want but things won't change. You have to roll up sleeves and clean it. No challenges here &amp;mdash; just a work that has to be done. The sooner &amp;mdash; the better.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/898376252540041162-6806199972369917714?l=serhiy.oplakanets.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/6806199972369917714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=898376252540041162&amp;postID=6806199972369917714&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/6806199972369917714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/6806199972369917714'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/2010/10/mess-is-just-mess.html' title='Mess is just a mess'/><author><name>Serhiy Oplakanets</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_Fh67HX8kDY4/SOUs3DOy99I/AAAAAAAAAAM/GPjjjsdHLzw/S220/DSC_0982.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-898376252540041162.post-7923697503951982927</id><published>2010-09-29T22:52:00.005+03:00</published><updated>2010-09-29T23:16:51.260+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lessons learned'/><category scheme='http://www.blogger.com/atom/ns#' term='mockito'/><title type='text'>Release as late as possible, resist adding new features as long as possible</title><content type='html'>&lt;p&gt;Recent &lt;a href="http://code.google.com/p/mockito-python/issues/detail?id=3"&gt;issue&lt;/a&gt; in Mockito for Python made me seriously think on how I release and add features. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The story started the day I decided to add feature called "spying on real objects" to Mockito. Ideas was good so I quickly implemented it. Then, strangely, I got this feeling like I'm doing something wrong. I started thinking that maybe I am missing something, maybe I don't have all use cases covered by unit tests and so on. It quickly disappeared together with a cup of coffee and a cigarette. I quickly made new release, added documentation and uploaded version to repository. Done.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;After two weeks, when I finally got time to look at mockito, I found a bug report regarding that same feature. And it turned out a really big issue. Not even an issue! The whole design of feature was wrong. The report even made think if adding that feature was really a good idea. As people started misunderstanding it and it made tiny API of mockito heavier. Gosh!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Today, understanding a fact that time machine is not yet invented, with a coffee and cigarette on a balcony, I made myself a promise: "release as late as possible and resist adding new features as long as possible". Funny thing that I actually knew it from all that nifty books. Hopefully, learning this lesson on my own mistake will imprint it in my brain forever.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/898376252540041162-7923697503951982927?l=serhiy.oplakanets.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/7923697503951982927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=898376252540041162&amp;postID=7923697503951982927&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/7923697503951982927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/7923697503951982927'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/2010/09/release-as-late-as-possible-resist.html' title='Release as late as possible, resist adding new features as long as possible'/><author><name>Serhiy Oplakanets</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_Fh67HX8kDY4/SOUs3DOy99I/AAAAAAAAAAM/GPjjjsdHLzw/S220/DSC_0982.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-898376252540041162.post-7729991605132691778</id><published>2010-03-02T22:33:00.006+02:00</published><updated>2010-03-02T23:50:52.556+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='mockito'/><title type='text'>Endotesting! That's it!</title><content type='html'>&lt;p&gt;Last couple of weeks I'm constantly trying to sell &lt;a href="http://mockito.org/"&gt;Mockito&lt;/a&gt; to everybody around. I find it the only mocking&lt;sup&gt;*&lt;/sup&gt; framework for TTDing. However in discussions like EasyMock vs Mockito, expecting vs spying, strict vs nice and so on I was really missing good arguments. I could tell you many things about rigidity and fragility of tests, about maintainability and so on but a strong feeling that it's not all wasn't leaving me. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Today, when looking for a reason why expect-run-verify frameworks gained such a big popularity and what was driving them, I finally found that argument and it has a name - &lt;a href="http://connextra.com/aboutUs/mockobjects.pdf"&gt;Endotesting&lt;/a&gt;. Read &lt;a href="http://connextra.com/aboutUs/mockobjects.pdf"&gt;the paper&lt;/a&gt;, it's very interesting.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The intent of endotesting, and a solution called Mock Objects had a good intention. Those guys back at 2000's were facing issues with discovering bad indirect interactions in complex systems and they really needed a tool to find them fast. A tool that will fail at exact place where unwanted or improper interaction is met. Stack traces were invaluable, mock had to be strict as it could be the only way to discover unwanted operations on your objects or subsytems. The mock object they imagined(and yes, needed) is a kind of endoscope to find breakages in internal organs.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Hey! is this really the tool we need today? No, no and no. Problems we are solving with unit testing nowadays totally differ from those ten years ago. How hard is it to find a breakage in one to twenty LOC unit you're testing compared to complex ensemble of object interactions in systems written ten years back? Even more, in context of Test-First Development a breakage usually means that your code is simply not created yet or you messed around with assumptions; when your expected interaction under injected object doesn't happen you normally can find the issue in seconds.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now it's time to answer yourself open and honest - do you really read stack traces of test failures that often? If you do - you're not writing your test before code, start doing it right now!&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The thing I want to make clear, is that I do think concepts of Mock Objects and strict test are really important and usable, but on some higher level, say, Integration Testing.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;sup&gt;*&lt;/sup&gt; Mockito &lt;a href="http://monkeyisland.pl/2008/03/21/lets-spy/"&gt;isn't really a mocking framework&lt;/a&gt; but for simplicity we can call it so, right?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/898376252540041162-7729991605132691778?l=serhiy.oplakanets.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/7729991605132691778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=898376252540041162&amp;postID=7729991605132691778&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/7729991605132691778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/7729991605132691778'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/2010/03/endotesting-thats-it.html' title='Endotesting! That&apos;s it!'/><author><name>Serhiy Oplakanets</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_Fh67HX8kDY4/SOUs3DOy99I/AAAAAAAAAAM/GPjjjsdHLzw/S220/DSC_0982.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-898376252540041162.post-6493281867789125407</id><published>2010-02-20T19:18:00.005+02:00</published><updated>2010-03-08T13:39:30.251+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python3k'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='mockito'/><category scheme='http://www.blogger.com/atom/ns#' term='distribute'/><title type='text'>Mockito Python3k Port</title><content type='html'>&lt;p&gt;Ported the &lt;a href="http://code.google.com/p/mockito/wiki/MockitoForPython"&gt;python version&lt;/a&gt; of &lt;a href="http://mockito.googlecode.com/"&gt;the best mocking framework&lt;/a&gt; to Python3000. Sources/Downloads are on &lt;a href="http://github.com/soplakanets/mockito-python3"&gt;github&lt;/a&gt;. Also available at &lt;a href="http://pypi.python.org/pypi/mockito-python3/0.1"&gt;Cheese Shop&lt;/a&gt;, of-course.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;UPDATE: &lt;/b&gt;Mockitoes for 2.x and 3.x are now merged together. You can find latests sources on &lt;a href="http://bitbucket.org/szczepiq/mockito-python/overview/"&gt;BitBucket&lt;/a&gt;. Many thanks to &lt;a href="http://pypi.python.org/pypi/distribute"&gt;Distribute&lt;/a&gt; committers and Armin Ronacher for &lt;a href="http://lucumr.pocoo.org/2010/2/11/porting-to-python-3-a-guide"&gt;useful blog post&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/898376252540041162-6493281867789125407?l=serhiy.oplakanets.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/6493281867789125407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=898376252540041162&amp;postID=6493281867789125407&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/6493281867789125407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/6493281867789125407'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/2010/02/mockito-python3k-port.html' title='Mockito Python3k Port'/><author><name>Serhiy Oplakanets</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_Fh67HX8kDY4/SOUs3DOy99I/AAAAAAAAAAM/GPjjjsdHLzw/S220/DSC_0982.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-898376252540041162.post-7887188762102721290</id><published>2009-11-26T16:05:00.006+02:00</published><updated>2009-12-31T15:22:21.442+02:00</updated><title type='text'>Summary of this Year</title><content type='html'>This year is almost over and I'd like to summarize it a bit for myself. Since I promised myself to write only work-related stuff in this blog most of points below will be rather technical or such that relate to my professional activity. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Wins&lt;/h4&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt; Started learning Python and Java.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt; Tried my self as a coach, not really successful but it was definitely worth trying.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt; Participated in programming contest which identified my weak places, the most relevant were standard algorithms and ADTs.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt; Improved my knowledge of standard algorithms and ADTs. Many thanks to &lt;a href="http://ocw.mit.edu/"&gt;MIT OpenCourseWare&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt; Improved my interviewing skills while interviewing couple dozens of PHP/Python engineer candidates at &lt;a href="http://www.lohika.com"&gt;Lohika&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt; Met two great guys, Denys and Anton, whom I had many enjoyable programming evenings with. I learned a lot from them in both professional and personal meaning. Thank you guys!&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Fails&lt;/h4&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Tried myself as TeamLead for quite a short time. However long enough to see that I don't see myself a good TeamLead (or any other kind of manager) in future. I'm techie. Period.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Started many in-house projects with my friends and never finished any of them. Looking back at those I see that we normally gave up with them mostly after the technically most interesting part was done.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;26 (for today) drafts of blog posts never finished.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Plans for Next Year&lt;/h4&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;The biggest plan for next year is to change a job. I like my current, but I'm working as outsourced contractor, which has way too many disadvantages.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Continue learning Java, maybe even get some certification like SCJP.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Continue Improving coaching and presenting skills.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Continue blogging. I find it pretty interesting and a nice way to systemize and share knowledge.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Finally finish at least one or two in-house projects.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Become a TechLead at Lohika. Will let me participate in new interesting projects.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Improve my English.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Those are not all, but most important points from top of my head. Should be fun to go through this list next End of Year. &lt;br /&gt;Cheers.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/898376252540041162-7887188762102721290?l=serhiy.oplakanets.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/7887188762102721290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=898376252540041162&amp;postID=7887188762102721290&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/7887188762102721290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/7887188762102721290'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/2009/11/summary-of-this-year.html' title='Summary of this Year'/><author><name>Serhiy Oplakanets</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_Fh67HX8kDY4/SOUs3DOy99I/AAAAAAAAAAM/GPjjjsdHLzw/S220/DSC_0982.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-898376252540041162.post-2477820632737410168</id><published>2009-11-14T21:32:00.014+02:00</published><updated>2010-01-22T12:23:51.813+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sweet wtf'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python: Function Argument Default Value Gotcha</title><content type='html'>Nothing new for experienced python developers, but really annoying for beginners. Try this piece of code:&lt;br /&gt;&lt;script src="http://gist.github.com/283669.js?file=wrong.py"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The output of this will be:&lt;br /&gt;&lt;script src="http://gist.github.com/283669.js?file=output.txt"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Dude, what just happened? See, python calculates function arguments' default values on function definition time. So our default argument &lt;i&gt;list&lt;/i&gt; is actually a reference that never changes. Hence we always modify same variable when calling &lt;i&gt;append&lt;/i&gt; with default &lt;i&gt;list&lt;/i&gt;.&lt;br /&gt;Even knowing the &lt;a href="http://docs.python.org/reference/executionmodel.html"&gt;pythons execution model&lt;/a&gt; this is one of those things that can cause what I call a "sweet wtf moment" and make you start a debugger. Which you of course hate doing cause you're TDDing, right? :)&lt;br /&gt;&lt;br /&gt;Workaround? Sure:&lt;br /&gt;&lt;script src="http://gist.github.com/283669.js?file=correct.py"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;More info in &lt;a href="http://docs.python.org/reference/compound_stmts.html#function-definitions"&gt;Python Manual&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Download &lt;a href="http://gist.github.com/gists/283669/download"&gt;source code of examples&lt;/a&gt; in this post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/898376252540041162-2477820632737410168?l=serhiy.oplakanets.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/2477820632737410168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=898376252540041162&amp;postID=2477820632737410168&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/2477820632737410168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/2477820632737410168'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/2009/11/functions-default-arguments-evaluation.html' title='Python: Function Argument Default Value Gotcha'/><author><name>Serhiy Oplakanets</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_Fh67HX8kDY4/SOUs3DOy99I/AAAAAAAAAAM/GPjjjsdHLzw/S220/DSC_0982.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-898376252540041162.post-8327420816635156377</id><published>2009-09-29T12:09:00.002+03:00</published><updated>2009-09-29T12:21:47.527+03:00</updated><title type='text'>Agile Blog Post</title><content type='html'>This is an Agile Blog Post. I started with the &lt;a href="http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html"&gt;Simplest Thing That Could Possibly Work&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is the end of Agile Blog Post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/898376252540041162-8327420816635156377?l=serhiy.oplakanets.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/8327420816635156377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=898376252540041162&amp;postID=8327420816635156377&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/8327420816635156377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/8327420816635156377'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/2009/09/agile-blog-post.html' title='Agile Blog Post'/><author><name>Serhiy Oplakanets</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_Fh67HX8kDY4/SOUs3DOy99I/AAAAAAAAAAM/GPjjjsdHLzw/S220/DSC_0982.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-898376252540041162.post-9127687092114322569</id><published>2009-07-30T19:04:00.003+03:00</published><updated>2009-07-31T15:37:47.716+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tech Talks'/><category scheme='http://www.blogger.com/atom/ns#' term='Caching'/><title type='text'>Caching Basics Tech Talk</title><content type='html'>Today I gave a Tech Talk about basics of caching at &lt;a href="http://www.lohika.com/"&gt;Lohika&lt;/a&gt;. Was not so bad taking into account that it was my first experience.&lt;br /&gt;&lt;br /&gt;&lt;!-- Slideshare Widget --&gt;&lt;br /&gt;&lt;div style="width:425px;text-align:left" id="__ss_1791108"&gt;&lt;a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/soplakanets/caching-basics" title="Caching Basics"&gt;Caching Basics&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cachingbasics-090730084707-phpapp01&amp;rel=0&amp;stripped_title=caching-basics" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cachingbasics-090730084707-phpapp01&amp;rel=0&amp;stripped_title=caching-basics" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/soplakanets"&gt;Serhiy Oplakanets&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- End Slideshare Widget --&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.slideshare.net/soplakanets/caching-basics"&gt;Slides&lt;/a&gt; available for download on &lt;a href="http://www.slideshare.net/soplakanets"&gt;my account on SlideShare&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/898376252540041162-9127687092114322569?l=serhiy.oplakanets.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/9127687092114322569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=898376252540041162&amp;postID=9127687092114322569&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/9127687092114322569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/9127687092114322569'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/2009/07/caching-basics-tech-talk.html' title='Caching Basics Tech Talk'/><author><name>Serhiy Oplakanets</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_Fh67HX8kDY4/SOUs3DOy99I/AAAAAAAAAAM/GPjjjsdHLzw/S220/DSC_0982.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-898376252540041162.post-4260431954640321067</id><published>2009-07-23T11:56:00.016+03:00</published><updated>2009-12-22T16:14:56.276+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='Configuration Files'/><title type='text'>Configuration Files for Bash Scripts</title><content type='html'>At some point of time I realized I need configuration files for bash scripts I use for automation of daily work. So I started looking for possible solutions. There are many options people propose on the Net: sed/awk to parse them, custom functions, XML parser, etc. But all of them are either heavy or hardly reusable. I even disappointed and started moving some of my bash scripts to Python, but recently my friend pointed me to simple and elegant solution which is based on using the &lt;a href="http://ss64.com/bash/period.html"&gt;`source' command&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To check it out create a config file `config.cfg' with following content&lt;br /&gt;&lt;pre class="prettyprint lang-bash"&gt;MESSAGE="WOW! It's so simple, fast and elegant"&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;And our test file `test.sh'&lt;br /&gt;&lt;pre class="prettyprint lang-bash"&gt;#!/usr/bin/env bash&lt;br /&gt;source config.cfg&lt;br /&gt;echo $MESSAGE&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;You can even make it shorter using the dot command which is synonym for source&lt;br /&gt;&lt;pre class="prettyprint lang-bash"&gt;.  config.cfg&lt;/pre&gt;&lt;br /&gt;&lt;em&gt;Note the space between dot and file name&lt;/em&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Make it executable&lt;br /&gt;&lt;pre class="prettyprint"&gt;chmod +x ./test.sh&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:monospace, -webkit-fantasy;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style="font-size:13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;And run it&lt;br /&gt;&lt;pre class="prettyprint lang-bash"&gt;./test.sh&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Nice, isn't it?&lt;br /&gt;Here is how it works. When a script is run using `source' it runs within the existing shell. So any variables that are declared in loaded script are available after script completes. And in bash the line in format NAME=VALUE means &lt;a href="http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html"&gt;declaring of variable&lt;/a&gt;. &lt;div&gt;Just for sanity's sake I recommend always quote values don't to have issues with built-in commands, reserved words, etc.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Download &lt;a href="http://serhiy.oplakanets.com/downloads/source.tar"&gt;example source code&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/898376252540041162-4260431954640321067?l=serhiy.oplakanets.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serhiy.oplakanets.com/feeds/4260431954640321067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=898376252540041162&amp;postID=4260431954640321067&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/4260431954640321067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/898376252540041162/posts/default/4260431954640321067'/><link rel='alternate' type='text/html' href='http://serhiy.oplakanets.com/2009/07/configuration-files-for-bash-scripts.html' title='Configuration Files for Bash Scripts'/><author><name>Serhiy Oplakanets</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_Fh67HX8kDY4/SOUs3DOy99I/AAAAAAAAAAM/GPjjjsdHLzw/S220/DSC_0982.jpg'/></author><thr:total>0</thr:total></entry></feed>
