Ali Özgür - The Pragmatic Developer

My Amazon.com Wish List

RecentComments

Comment RSS
aliozgur posted on February 22, 2010 10:01

We have been busy developing our new baby JiraTouch for the last 3 months. It has been a tough journey with lots of unknowns and new things. Platform was new, development tools were new and the team was new. The only knowns were Jira and the C# language. I would like to share some of my observations in this blog post.

What is JiraTouch?

You can read JiraTouch features to learn more about JiraTouch.

You can watch video tutorials to see JiraTouch in action.

You can buy JiraTouch from AppStore.

Jira and SOAP API

No need to talk about the quality of Jira software on its own. But I'm sorry that Jira SOAP API is not as complete as the product itself. The most serious problem is the versioning dilemma of the SOAP API. SOAP API is introduced since Jira version 3.0 but over the time (Recent version is Jira 4.01) there have been lots of changes with the API. Change is normal and we do not expect all aspects shall be covered at once, since the product itself matures and changes so does the SOAP API. But I would be more happy if Jira guys developed a good API versioning strategy with good API change documentation. For example with no specific versioning information included in the wsdl you get different properties for the same Type. One perfect example is RemoteComment type, this type has changed dramatically through Jira versions. Here are examples of the WSDL for different jira versions

This snippet is from the wsdl of a Jira 3.6 installation

<complexType name="RemoteComment">
  <sequence>
   <element name="body" nillable="true" type="xsd:string"/>
   <element name="id" nillable="true" type="xsd:string"/>
   <element name="level" nillable="true" type="xsd:string"/>
   <element name="timePerformed" nillable="true" type="xsd:dateTime"/>
   <element name="username" nillable="true" type="xsd:string"/>
  </sequence>
</complexType>

This is wsdl snippet for RemoteComment from Jira 4.01

<complexType name="RemoteComment">
<sequence>
<element name="author" nillable="true" type="xsd:string"/>
<element name="body" nillable="true" type="xsd:string"/>
<element name="created" nillable="true" type="xsd:dateTime"/>
<element name="groupLevel" nillable="true" type="xsd:string"/>
<element name="id" nillable="true" type="xsd:string"/>
<element name="roleLevel" nillable="true" type="xsd:string"/>
<element name="updateAuthor" nillable="true" type="xsd:string"/>
<element name="updated" nillable="true" type="xsd:dateTime"/>
</sequence>
</complexType>

Another very major difficulty I think is how Jira handles/expects date and time values. When you get some entity having datetime data from Jira with the SOAP API, you get UTC formatted datetime value and that is ok. But since some specific Jira versions does not provide information about the Jira server's datetime we are not able to perform timezone specific conversions which in turn causes our clients to view wrong or more specifically locale datetime values and as well submit locale datetimes to the Jira server. To handle this deficiency we had to include in JiraTouch a time zone selection if we could not get server datetime automatically from Jira server, which is an extra configuration overhead for our clients. Jira's date and time handling is long debate in Jira community and among Jira customers as well, current Jira versions can not handle different time zones as far as we investigated Jira customers have requirements about this concern and we hope Jira guys will develop a smart way to handle different timezonse at some point.

Custom fields were another headache. Jira has very handy and highlghy configurable custom field support. You can define most of the custom fields you need, but SOAP API has limited support for the custom fields. One major problem is you get dictionary of custom fields for a RemoteIssue type but you just have custom field id and the value, there is no label/name included.

Here is the wsdl definition for a remote custom field

<complexType name="RemoteCustomFieldValue">
 <sequence>
   <element name="customfieldId" nillable="true" type="xsd:string"/>
   <element name="key" nillable="true" type="xsd:string"/>
   <element name="values" nillable="true" type="impl:ArrayOf_xsd_string"/>
 </sequence>
</complexType>

Since you get no label what shall we display to the user the id and the current value? Not so user friendly. The only way to get label/name of the custom fields is through getCustomFields soap method, but there is one little problem you have to be logged in as an administrative user in order to call that method! That is not so cool but with some tweaking we could overcome this limitation without requiring adminsistrative login.

The last thing I want to point about Jira SOAP API limitations is that mighty "time tracking" field dilemma, more generally some explicitly required but not included on RemoteIssue type properties. These properties are somehow predefined custom system fields but createIssue method of SOAP API does not support these kind of fields properly. Again to overcome this issue some little fancy tricks need to be done.

These were some of the problems we faced with the well known part of the project.

Mono, MonoDevelop and MonoTouch

I believe that Mono and MonoTouch are very valuable efforts. I will not waste your time telling you why they are valuable you can find lots of arguments around, but as a Microsoft platform developer and a .NET developer I'm pleased with the existence of Mono and MonoTouch.

The major headache we had during JiraTouch development regarding Mono was MonoDevelop. Compared to Visual Studio MonoDevelop feels like a not so cool notepad. The worst thing about MonoDevelop is unstability, it might crash, freeze or code editor just decide not to paint some of the brackets you type. For example if you reference assemblies with auto incremented version numbers (that is 1.0.*) MonoDevelop can not refresh your references successfully and as a result you get "missing type" compile time errors. MonoDevelop debugger also has some problems, you may need to click multiple times so that debugger can be attach to IPhone simulator, MonoDevelop may crash while you try to evaluate a variable during debugging, you may get "Can not evaluate" error while trying to see variable values and you can not just copy/paste the contents of the evaluation window.

We designed JiraTouch so that we could develop Model and UI assemblies seperately, so for a long time we tried to develop Model assembly on OpenSUSE with MonoDevelop to ensure maximum level of framework compatibility when we reference that assembly from the UI (IPhone application actually) which was being developed on Mac OSX. After spending some time struggling with MonoDevelop we decided to switch to Visual Studio and do rest of the Model assembly development with Visual Studio which in turn caused some framework incompatibilities I will demonstrate you just in a second.

Another major problem was missing System.Web.Services.dll in MonoTouch. During development we used to generate Jira service proxy on openSUSE, include the generated code in the project and reference an unofficial version of System.Web.Services.dll. That approach worked well for a while until we decided to compile our IPhone application with "Link SDK assemblies only" option which caused our approach to fail. So we had to give up with that linker option and try to survive with a larger application size, until Mono decided to include an official System.Web.Services.dll for MonoTouch which just worked well with the linker option.

We faced framework level implementation differences as a result of choosing Visual Studio as the main tool for Model development. The biggest issue we faced was with XmlReader and XmlTextWriter implementations. In Microsoft's implementation WriteNode works perfectly with element attributes while Mono implementation just writes the first attribute and ommits the rest. So we had to traverse all elements and perform WriteAttributes, WriteRaw, WriteStartElement and WriteFullEndElement based on the element types. This difference was hard to discover and hard to resolve which we had to spend much more time than we expected.

Yet another frameowork level implementation difference was with HttpWebRequest.PreAuthenticate we faced while developing the Social integration parts of JiraTouch. On Microsoft and Mono when you specify PreAuthenticate to be true and add an Authorization header to the request both frameworks continue to send that header to the server after the first request, but on MonoTouch Authorizaton header is not sent to the server after the first request which is absolutely a normal behaviour. Again this difference caused us couple of frustrating debug sessions, but we are happy that we discovered that issue before launching JiraTouch.

The last difficulty we faced I want to mention is that magic "Link SDK assemblies only" option. If you build you IPhone application with this switch MonoTouch performs some optimizations during compile time thus producing a smaller application in size. Smaller size means a lot in iTunes and AppStore world, because if your application(actually ipa file, which is compressed package of your application) is larger than 10MB you will not be listed for OTA downloads which in turn means that you will not reach some portion of IPhone users. So we decided to use this option, but we ignored some facts about using this options and Mono documentation does not specify exactly what considerations apply if we use this options. It is simply stated that some of the reflection and serialization related functionality can cause runtime errors. Yes that is true we had runtime errors but we would be pleased if the compiler could warn us about these issues. One simple example was the runtime error we got from a code snippet which was simply performing Linq query on an array of enumerations. The code was something like this

var enums = Enum.GetValues(typeof(SomeEnumerarion));

var selectedValue = from e in enums where e.ToString() == "EnumValue1" select e;

The sample code snippet worked well while debugging with "Link SDK assemblies only" option but when we tested JiraTouch on an IPhone we used to get runtime errors regarding MonoTouch and AOT (ahead of time compiling, since on IPhone JIT compilation can not be performed MonoTouch uses AOT compiling to support generics, linq and other stuff). We just changed the code and dropped the Linq query and the problem was solved. As I said we would be happier if MonoTouch compiler warned us with that possible runtime problem.

Review Process; iTunes and AppStore

We had no problems during the process of submitting JiraTouch for review over iTunes. We submitted on the weekend and JiraTouch status changed to "In Review" on Tuesday and we got approved on Friday. We got the approval within 3 days that was amazing.

What is our vision?

We argue that JiraTouch is the most complete Jira client specifically optimized for IPhone. We tried to cover most of the Jira functionality so that a Jira user can perform almost everything with JiraTouch. We believe that we succeeded to get to that completeness level as far as Jira SOAP API allowed us and a little bit beyond what Jira SOAP Api offers. Our vision was to provide the highest possible level of Jira functionality with some unique features like Social integration, which allows JiraTouch users to update their twitter,facebook, linkedin and yammer accounts.

In the future we intend to provide more unique features to JiraTouch users, which will be focused mainly on sharing and social communities. We already started evaluating these unique ideas and hope to include these fatures with the next version of JiraTouch.

What is PragmaTouch?

We decided to gather all touch enabled device software development under the PragmaTouch brand. PragmaTouch will be the brand supporting primarly JiraTouch. We will provide consulting and developing custom touch enabled device projects under PragmaTouch brand as a group of independent software developers.

Epilogue

I would like to thank to my colleagues Tolga and Ahmet. They did a fantastic job and helped me much while managing this project.

 


Posted in: IPhone , MonoTouch  Tags:

Downloads

Original project is here

Modified binaries: IIS_LogAnalyzer_Bin.rar (360.01 kb)

Patch file : Indihiang_LogAnalyzer_FTPSupport.patch (170.94 kb)

Screen Shots

 

 


 

Note for Vista Users

Modified version creates a TempDir under the application installation folder and downloads files there. Vista does not allow regular user to create directories under Program files so if you install the application under Program Files , right click on the Indihiang.exe, click Properties and check "Run this program as an administrator" option found in Compatibility page.

 


aliozgur posted on October 7, 2009 10:47

Yesterday I visited Rob Conery's blog and the post about commercial SubSonic support options made me think again about the open source philosophy. In my opinion Rob must decide in which category of Open Source is SubSonic located.

  • Is it a real open source project as defined by OSI
  • Is it an open source project in a way ASP.NET MVC is

If SubSonic is in the first category, I believe NHibernate is in that category, Ayende’s commerical support offering is not acceptable. Since bug fixes are included in that offering and Rob or Ayende are commiters that would not sound right to the community.

If SubSonic is in second category and Rob decide that SubSonic is open source but main official release is maintained and owned only by him or a company that commericial support offering would be ok.

Perfect Examples

Following OSS examples are very well suited to define my objection

Linus Torvalds does not offer bug fixes as a commerical support for the official Linux kernel. He does not because he is the main authority, and the unpaid authority, who decides if a bug fix or patch be applied to the official release of the kernel. (I do no think he has the time to review all submitted patches but he in a way organized the inner workings) But we all know that Suse and RedHat offer bug fixes and patches for their own distribution, which is understandable and valid. I do not mind the way RedHat or Suse patches and bug fixes are applied to the official kernel releases.

Another example is the Mozialla Foundation. If NHibernate had a non profit foundation as Mozilla and the foundation offered commercial support via kind of Mozilla Corporation that would be OK too. And I want to remind you that Mozilla like foundations do not distribute share profit to any third parties.

Questions

  1. As far as I know NHibernate is not copyrighted to anybody or any entity. So may other contributors claim copyright for the bugs they introduce which may cause some complications?
  2. The material itself and the functionality that material provides is not paid in OSS projects. Does offering commercial bug fix support right for the official release of the project cause the material to have some sort of monetary value, since fixing bugs is commercialized which means introducing bugs may be commercialized too?
  3. What if I, as a non commiter to NHibernate project, wanted to offer commercial bug fix support too? Do you think that project leads would allow me to be a committer just beacuse of that even if I'm not qualified to be a commiter? Shall I interpret Ayende as monopoly in NHibernate community context? Don't you think that being a virtual/possible monopoly conflicts with the open source?
  4. If an OSS is not copyrighted to anybody or any entity, do you think that OSS project leads hold legal rights to decide whom to let in or kick out?


Posted in: General Development  Tags:
aliozgur posted on August 14, 2009 12:32

For a while I'm trying to align a technology toolset for Web 2.0 development. Recently I decided to go with Microsoft .NET technologies and JQuery.

Here are the tools I'm provisioning to utilize

  • ASP.NET MVC and JQuery
  • ADO.NET Entity Framework
  • WCF
  • May be ADO.NET Data Services and ADO.NET Dynamic Data

There is already a jQuery LighBox Module for Cuyahoga 1.6 but in my case I have a Cuyahoga 1.5.0 installed with some custom modules and can not use that module. Here are the steps you have to perform to use jQuery LighBox Plugin with a Cuyahoga 1.5.x installation.

  1. Dowload jQuery LighBox plugin from here.
  2. In your Cuyahoga installation root browse to js folder and create JQueryLightBox folder under that js folder
  3. Open jquery.lightbox-0.5.min.js file found in the downloaded package and replace
    • 'images/lightbox-ico-loading.gif' with '/images/lightbox-ico-loading.gif'
    • 'images/lightbox-btn-prev.gif' with '/images/lightbox-btn-prev.gif'
    • 'images/lightbox-btn-next.gif' with '/images/lightbox-btn-next.gif' 
    • 'images/lightbox-btn-close.gif'with '/images/lightbox-btn-close.gif'
    • 'images/lightbox-blank.gif' with '/images/lightbox-blank.gif'
    and save your changes
  4. Copy jquery.js and jquery.lightbox-0.5.min.js files found in the downloaded package to JQueryLightBox folder created in the previous step
  5. Create a folder named css under your Cuyahoga installation root and create JQueryLightBox folder under that css folder
  6. Copy jquery.lightbox-0.5.css found under css folder inside the downloaded jQuery LighBox package to JQueryLightBox folder created in the previous step
  7. In your Cuyahoga installation root browse to Images folder and copy the image files found in under images folder of the downloaded jQuery LighBox package to the Cuyahoga Images folder.
  8. In your Cuyahoga installation browse to Templates folder and find the ascx file under the current template folder you are using
  9. In the head section of your ascx file add these lines

  10.   <script type="text/javascript" src="../../js/JQueryLightBox/jquery.js"></script>
      <script type="text/javascript" src="../../js/JQueryLightBox/jquery.lightbox-0.5.min.js"></script>
  11.  At the end of the ascx file just before the closing of body tag add the following js code
  12. <script type="text/javascript">
    $(function() {
        $('a.lightbox').lightBox(); // Select all links with lightbox class
    });
    </script>

  13. Add links to your images to enable jQuery LightBox for your images. Here is the template link 
  14.  <a title="Title here" class="lightbox" href="Link to your original image file"><img border="0" alt="" src="Link to the thumbnail image file if you wish to use thumbnails, if not you can remove this img tag" /></a>
     
  15. See jQuery LightBox in action


Posted in: Cuyahoga  Tags:
aliozgur posted on June 2, 2009 16:59

After being named as Best General Database Tool by CodeProject readers PragmaSQL decided to publish a free Personal Edition.

You can download PragmaSQL Personal from here


Posted in: PragmaSQL News  Tags:
PragmaSQL was named as Best General Database Tool by The Code Project’s members.
Members were asked to rate their favorites on CodeProject. The Code Project staff then compiled the highest rated listings, awarding the highest ranked in each product category. The results reflect actual perceptions of what developers value. Each codeproject.com member decides which companies or products deserve recognition, based on in-the-field experience.  

Posted in: CodeProject  Tags:
aliozgur posted on May 18, 2009 16:46

Why?

Some time ago while I was working on a project, that was a top secret project so can not give more details Smile,  I realized that I've produced some sort of weird code that checks if an interval (Start,Stop integer value pair) intersects with another interval. Right after unit testing and commiting the code I felt like there is something wrong wih me. Here are the details

Nothing Fancy

Here is the code of my Interval structure. There is nothing fancy about this structure it is used to hold two integer values and performs range checking in the constructor to guarantee that start value is always smaller or equal to stop value.

public struct Interval
{
private int _startValue;
public int StartValue
{
get { return _startValue; }
private set { _startValue = value; }
}

private int _stopValue;
public int StopValue
{
get { return _stopValue; }
private set { _stopValue = value; }
}

public Interval(int startValue, int stopValue)
{
if (startValue > stopValue)
throw new TypeInitializationException("Interval",
new Exception("Provided start value is greater than the provided stop value."));

_startValue = startValue;
_stopValue = stopValue;
}

public bool IntersectsWith(Interval interval)
{
//TODO: Check if this intersects with the provided interval
}
}

 

Conventional Way

Conventional way of implementing that IntersectsWith method is to 1) write some if/else blocks or 2) to combine a single return statement  to cover all of the cases illustrated on the following image

My Problem

But somehow I did not choose the conventional implementation and I decided, in fact by reflex, to re-model Interval objects as rectangles with 1px in height , place them on xy coordinate system and check if two rectangles intersect or are tangent to each other. Here is my weird IntersectsWith implementation

 

public bool IntersectsWith(Interval interval)
{
  Rectangle r1 = new Rectangle(StartValue, 0, StopValue - StartValue, 1);
  Rectangle r2 = new Rectangle(interval.StartValue, 0, interval.StopValue - interval.StartValue, 1);

  return r1.IntersectsWith(r2) || (r1.X + r1.Width == r2.X) || (r2.X + r2.Width == r1.X);
}

 

Questions to myself

  • Is this weird implementation is a result of too much analytical thinking?
  • Is this weird implementation is a result of too much abstract modeling I have to do to perform my job well?
  • Shall I see a therapist?
  • Is this weirdness a common pattern among developers?
  • Shall I ask this as an interview question? And what shall I do with people implementing this method like me and not like me?
  • How will my colleagues feel when they have to read my wierd IntersectsWith implementation?
  • Shall I be ashamed of myself? 

Code

WeirdIntersectsWith.rar (23.00 kb)


Posted in: .NET Development , General Programming   Tags:

I'm currently working on some small projects and an enterprise level case study project where I decided to use SubSonic which is a lightweight open source ORM for .NET led by Rob Conery. I can say that SubSonic is really lightweight and is really easy to use, but as might be expected has some minor configuration overhead. SubStage developed by Eric Kemp is a must have if you are using SubSonic, but this tool lacks a very important feature IMHO. All your subsonic related project configuration is kept inside a predefined MasterStore.xml file which means you only have a single file for all your subsonic projects. In this scenario it is not easy/handy to attach your substage configuration to your project source code.

To overcome this problem I modified SubStage source code (built against SubSonic 2.2) and added "Load Master Store" and "Save Master Store As" File menu items. I posted the patch to Eric Kemp but I do not know if the patch will be applied in newer version so I publish both compiled SubStage and the Subversion Patch file.

Downloads

SubStage_2.2_With_MasterStore_LoadSave.rar (1.69 mb)

SubStage_Patch_AliOzgur.patch (242.82 kb)


Posted in: .NET Development , C# , SubSonic  Tags:
aliozgur posted on January 30, 2009 13:10

The sample Ruby code has no syntax errors. What does the code through lines 3-5 mean? And what is printed to the screen/console?

Any Suggestions ? Smile

 

class Sample
  attr_writer :name
  attr_reader :name do
     "Mr. " + @name
  end
end

s = Sample.new
s.name = "Ali"
puts s.name

 


Posted in: General Development , Ruby  Tags: