May 8, 2016

 

Software documentation

Recently I don't see almost any diagrams in software docs. It seems like the nowadays developers cannot also create any ascii-graphics like this BufferStrategy class doc written 10+ years ago. None of such I've seen in Android docs (point me out to any please?).

Moreover some talented developers seems don't want to document at all. Check out this one, very complex UI behaviour class AppBarLayout.Behavior. It says: "The default AppBarLayout.Behavior for AppBarLayout. Implements the necessary nested scroll handling with offsetting." That's all. What exactly is necessary?

Yes, I've heard many times that mantra of idlers "code source is the best documentation for itself". Without docs it requires sometimes hours or even days to know all the nuances of implementation. In total it requires additional man*years if some popular framework is poorly documented and decreases overall experience of developers and users for using such piece of technology.

So my friend, let's start documenting the sources we write with something more than the usual "f%ck off I'm busy"-style docs and comments that we see in so many docs by adding the details of implementation and side effects. And diagrams!

Labels: , , , , , , ,

July 11, 2014

 

WP8 - some troubles report

While releasing first commercial app for WP8 I had experienced following effects.

1. Beta app updates very unstable. Frequently the description is new, but xap itself is of previous version. I don't know workaround. Usually publish new version. You have to check version carefully on every launch.

2. If you have crashes (unhandled exceptions), these stack traces will be in dashboard only 4 (yes, four) days after exception happened. After all, not every crash is reported. Workaround: I ended up writing my own unhandled exception handler which sends reports to my own sever.

3. IAP logics is not so simple as it may be thought of when you use consumable products with your own server check. There's one pitfall: you must call CurrentApp.RequestProductPurchaseAsync() only from UI thread (or you will have and unhandled exception!), while LicenseInformation.IsActive IAP license testing calls must not be called from UI according to MSDN. So it seems good idea on "buy" click to show some "please wait" indicator and continue to work in new thread. But when time comes to make a purchase method call you don't have Dispatcher.Invoke() for synchronously executing in UI thread (I mean wait for result). Also, you have to deliver exceptions from UI thread to your own thread. Here's the way:

          //not UI thread. something like "new Thread(delegate(){ ...following code... }).Start();"
          AutoResetEvent waitHandle = new AutoResetEvent(false);
          Dispatcher.BeginInvoke(async () =>
          {
            try{
              await CurrentApp.RequestProductPurchaseAsync(productListing.ProductId, false);
            }
            catch (Exception e) {
              purchaseEx = e;
              log(print(e)); 
            }
            waitHandle.Set();
          });
          waitHandle.WaitOne();
Or course you have to handle exceptions from separate UI thread, otherwise you will have unhandled exception and crash.

4. RequestProductPurchaseAsync() leads to ProductLicense.IsActive = true. But nobody knows when. MSDN says ""

5. When user press Cancel (or Back button) during system purchase confirmation, CurrentApp.RequestProductPurchaseAsync() throws an exception. This is undocumented behaviour, so you have to catch general Exception (I've seen System.Runtime.InteropServices.COMException at 8.0, but nobody guarantees 8.1 have same). By the way, catching general Exception is called "no-go" by Microsoft. Very nice.

Actually, I did not found good code sample of working IAP for consumable and self-checking. I'm going to publish my code when I test it fully. See next post.

Labels: , , , , , , ,

June 29, 2014

 

Some WP8 in app purchase errors

Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
this means you call CurrentApp.RequestProductPurchaseAsync not from UI thread

error code 805a0194
(in a dialog) means that you need to publish your app (maybe in beta) via Store before you can test purchases.

Labels: , , , , , , ,

June 28, 2014

 

windows phone LINQ "already exists" issue on empty table

Update this happens not only when you have the only primary key field. Even when primary key is autogen, this exception happens when you put same value as you deleted previously in same DataContext session. I don't have workaround yet. Do you?

LINQ to SQL has strange effects when you try to reuse DataContext (re-creating of DataContext after every update/delete operation has different bad effect).

For example if your sole field is actually your primary key (it is unique at any moment and not null) and you delete it and in the same DataContext session insert same value, you will have InvalidOperationException. In my case the table is even empty!

  [Table(Name = "Receipts")]
  public class Receipt : PropertyChangedBase
  {
    protected String _s;
    public Receipt() { }
    public Receipt(String s) { _s = s; }

    [Column(IsPrimaryKey = false, CanBeNull = false, AutoSync = AutoSync.Always)]
    public String s
It seems that after delete you have to recreate DataContext. Will try this strategy.

Labels: , , , , , , ,

April 12, 2014

 

Some thoughts on programming

What is programming, how and why to learn it?

When I imagine someone who is complete novice for programming starting to learn it, for some reason I think of text mode editor with large clear white or green letters and command line. Or even Basic. But does anyone learn Basic today? I fear no. Then what environment do people start from?

When you have little environment (text and dark-screen graphics mode) and some book (or simple in-IDE docs), you can set simple goals and reach them with much pleasure. An example of such environments are QBASIC and VS installed with MSDN.

But what if one starts developing web apps with its almost indefinite features of JS frameworks (and even infinite number of frameworks themselves)? I don't event want to think of server-side part set-up and configuration: for novice it can be a nightmare (comparing to VS/QBASIC set-up, for example). The web app stack is just big and have many tactical questions: app layer, app server layer, HTTP transport layer (it's not so simple with its compatibility issues) and the very complex network layer, then client side browser with its issues, and OS aroma. This is not whole list of things web programmer must think about. Others are startegic questions: stability, high load, logging, security. Of course, one can use ready framework and LAMP out-of-the-box server setup, but no cheap real product can be completed without understanding underneath stack issues.

So does it help to learn programming when you have rich envoironment? Or is it better to have poor environment with more reachable goals? I don't know exactly :)

The other thing is motivation and energy.

For me, in programming I receive energy for completing the goals I set for myself. Of course, I had formal courses in school and university, and of course if the external goal was worth interest, I had real pleasure completing it.
But sometimes this is like living in a parallel world: goals I set for myself did not always correlate to some real-world valuable (for money) tasks. For example, I remember I sat the whole weekend optimizing image-scaling algorithm. Good thing, but not for what money was paid that time. Although I was able to speed-up that 70x comparing to straight-forward implementation and I was very proud of it :)

I believe that in programming the emotional feedback is the most important thing. Although programming itself is actually very unemotional and even sometimes boring subject.

But I believe programming is great and almost the most interesting profession, maybe after nuclear physics :-)

Labels:

February 11, 2012

 

Apple developer docs... (or: vs Java dev docs)

A thoughts of an old-school Java programmer while learning some iOS

..are not designed to be a fast-search-answer book. (search behaves bad actually). It's a tightly linked bundle of articles (with lots of html pop-up annotations!), which you have to read one after anohter. This creates a rich market of developers books, of course. But I'm not fan of overspending :-)

This stands in direct opposition to how Sun's Java docs were presented: to understand how to use library, one need to read only the class/interface descriptions (I can't remember I read package docs, anyone?); each class description is a very short and contains the concept of how it iteracts with others.

I think it comes from language differences: Java presents more plain classes without multi-file classes (.h, .m in ObjectiveC). So with proposed (by Sun?) javadoc inline style documentation Java classes are much easier to describe and support the changes.

Anyway, I spend more time to find information even in cases when I know what I'm looking for, comparing to Java SDK or ME docs or even Android docs.

For the Apple iOS docs, single place for navigating across whole bundle of articles could be very good.

Labels: , , ,

 

Bookmark: "Model-view-controller" pattern described

Don't remember who asked me for this, here's MVC description:
https://developer.apple.com/library/ios/#documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html

Labels: , , , , ,

March 29, 2011

 

Link: "Why MacOS X is unsuitable for web development"

http://developers.slashdot.org/story/11/03/28/2149206/Why-Mac-OS-X-Is-Unsuitable-For-Web-Development
no comments

Labels: , , , ,

November 3, 2010

 

Pointer events bounce on clicks

Yesterday made simple experiment: recorded in log coordinates (x,y) of pointer press, drags and release events at real devices. During experiment I only clicked (not scroll!) at screen using finger. Devices are: Nokia 5230 and Samsung S5230.
Results impressed me a lot: bounce is up to 23 pixels (for y up to 15, possibly because of finger shape)!
This mean that if you need to differentiate scroll from click, you have to implement some kind of filter that takes into account time and type of movements of pointer.

Labels: , , , , , , , , , ,

June 23, 2010

 

Notes on Clipping and translation in MIDP

To make less mistakes in MIDP graphics it's important to know how is it work. Actually, MIDP docs and books I've read describes clipping and translation very superficially.
The notes 1 and 3 described below was some a surprise for me.
1. Graphics calculates and stores clipping: a) on each clipRect() call; b) in absolute (screen) coords.
Example:
clipRect(0,0,50,25)
translate(0,-25)
fillRect(0,0,50,50)
rect is painted with height 25
you could expect nothing on screen, but it's wrong.
2. (obvious) Graphics' clipRect() offset is expected in current translated coords. (see example below in (3))
3. Graphics always have clipping enabled (by default is's equal to the whole paintable area size, different depending on fullscreen mode).
Example:

translate(0,-25)
clipRect(0,25)
translate(0,25)
fillRect(0,0,50,50)
you get nothing painted, because on clipRect() call clipping was intersected with default clipping -> become (w=0,h=0) which is stored. On second translate call clipping area is not recalculated.

Labels: , , , ,

December 5, 2009

 

J2ME: Workaround for "Class NoClassDefFoundError not found"

When you compile for CDLC 1.0 if you use SomeClass.class, you could get this error: "class file for java.lang.NoClassDefFoundError not found".
There're two ways of workaround: compile for CLDC 1.1 or use this style:
Class class = Class.forName("package.SomeClass");
instead of:
Class class = package.SomeClass.class;, although it has the right syntax.

Labels: , , ,

July 24, 2009

 

[J2ME] deadlock in canvas.paint, lcdui

If you need to have a critical section in Canvas.paint() override, double-check that you do not lock in same monitor when calling myCanvas.repaint(). Problem exists in this some specific configuration, when you have 2 threads. In [1, main for example] you do:
display.setCurrent(myCanvas); and in [2, newly created] you call:
myCanvas.repaint() in same critical section as in your paint() impl.
I had deadlock in this case, at least in some LCDUI implementations. The reason is that MIDP usually have its own critical section in setCurrent() (when calling paint() for the first time) and in repaint() (when adding repaint event into queue), so it cannot both add repaint request into queue and enter your paint()'s your critical section. Deadlock. So be careful ;-)

Labels: , , , , , , , , ,

March 9, 2009

 

Поиск ошибок в программе

Все слышали выражение "проще переписать заново, чем исправить". Это придумали те, кто не может исправлять ошибки в программах. В чем же заключается исправление ошибки в сложном и незнакомом коде?
Я не буду рассматривать все пути (которых разумеется бесконечность, возможно, правда, счетная), а расскажу один из путей на основе своего опыта недавнего исправления ошибки. Это не будет ссылкой на формальную верефикацию программ, которая в чистом виде слишком дорога для применения по причине необходимости полной формализации системного окружения.
Первый этап - локализация ошибки. Зачастую, при сложных алгоритмах и/или при неграмотной архитектуре это самый трудоемкий этап. Что такое локализация? Это значит найти, какой код работает не так, как надо. Логичен вопрос: а как надо? Поэтому надо осознать, как должен был по задумке работать алгоритм. Это самая сложная часть, если не приходится разбираться в незнакомом и недокументированном куске программы. В этом случае приходится рисовать диаграммы и декомпозицией от большего к меньшему находить смысл всех условий и вызовов. Результатом для алгоритма будет блок-схема в терминах смысла действий (для невычислительных алгоритмов желательно описание на естественном языке, что на первой итерации упрощает анализ хода выполнения; если ошибка не будет найдена, скорее всего придется анализировать все блоки алгоритма более формально, см ниже.)
Поскольку мы рассматриваем случай, что не тот, кто написал, ищет ошибку, то можно предположить, что код работал некоторое время, а значит, появился набор данных, на котором он перестал работать так, как надо ("контрпример").
Для локализации можно сравнивать работу кода с рабочим примером по сравнению с контрпримером. Рабочий пример должен иметь минимальное отличие (неформально; чтобы ход работы алгоритма отличался минимально) от контрпримера для того, чтобы найти локализовать ошибку как можно более точно. Иногда можно локализовать ошибку просто сравнивая, какие куски кода срабатывают в каких ситуациях (ошибка в условном переходе или ошибка в самом коде).
Анализ хода выполнения выглядит так: достаточно нарисовать ход выполнения для рабочего и контрпримера в терминах построенной ранее блок-схемы (желательно на естественном языке) и сравнить полученные описания. Разница ходов выполнения и будет локализовывать с определенной детализацией ошибку.
В случае, если в обоих вариантах выполняется один и тот же код, значит ошибка носит "вычислительный характер". В этом случае анализ должен носить более формальный характер. Для этого можно разбивать алгоритм на блоки (функции) и проверять такие характеристики, как область определения и область значений каждого блока; граничные значения и поведение на них, устойчивость и другие. Для локализации ошибки нужно иметь означивания переменных для каждого стыка выделенных блоков, сравнить их с найденными значениями и это может локализовать блок (для которого уже можно повторить процедуру).
Исправление ошибки, в особенности в модуле, от которого зависят другие модули, всегда является отдельной непростой задачей, поскольку требуется обеспечить работоспособность этих модулей. Проблема обостряется, когда нет возможности легко (читай: дешево) внести изменения в зависящие модули. Но об этом позже.

Labels: , , ,

This page is powered by Blogger. Isn't yours?