kenegozi.com

<form id='kenegozi' action='post'></form>

   
2008 Aug 24

Key-level locked cache - real life implementation

tagged as: asp.net 2.0 | c#

Following my post on key-level locked cache, I got the following piece of code from my friend Moran Benisty, implementing the same idea over XmlDocuments which is being loaded over the Internet, and ASP.NET's Cache.

 

This is a real life code. He's using it on a very large-scale website in production.

 

As usual - use at your own risk, and be kind enough to share thoughts and improvement ideas here for his use.

 

 

public static class XmlService
{
    private static Dictionary _locks = new Dictionary();

    public static XmlDocument GetXml(string url)
    {
        return GetXml(url, new TimeSpan(1, 0, 0), false);
    }

    public static XmlDocument GetXml(string url, TimeSpan timeToHold, bool autoRefresh)
    {
        if (HttpRuntime.Cache[url] as string == "Failed")
            return null;

        XmlDocument xml = HttpRuntime.Cache[url] as XmlDocument;
        if (xml != null)
            return xml;

        if (!_locks.ContainsKey(url))
            lock (_locks)
                if (!_locks.ContainsKey(url))
                    _locks.Add(url, new object());

        if (HttpRuntime.Cache[url] == null)
            lock (_locks[url])
                if (HttpRuntime.Cache[url] == null)
                {
                    xml = LoadXml(url);
                    if (xml != null)
                        HttpRuntime.Cache.Insert(url, xml, null,
                            DateTime.Now.Add(timeToHold),
                            System.Web.Caching.Cache.NoSlidingExpiration,
                            System.Web.Caching.CacheItemPriority.NotRemovable,
                            delegate(string dataKey, object value, CacheItemRemovedReason reason)
                            {
                                if (autoRefresh)
                                    GetXml(url, timeToHold, autoRefresh);
                            }
                    );
                    else
                        HttpRuntime.Cache.Insert(url, "Failed", null, DateTime.Now.AddMinutes(5), System.Web.Caching.Cache.NoSlidingExpiration);
                }

        xml = HttpRuntime.Cache[url] as XmlDocument;
        return xml;
    }

    private static readonly ILog _errorlog = LogManager.GetLogger("ErrorLogger");
    private static XmlDocument LoadXml(string url)
    {
        try
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Timeout = 3000;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            XmlDocument xml = new XmlDocument();
            xml.Load(response.GetResponseStream());
            return xml;
        }
        catch (Exception ex)
        {
            _errorlog.Error(ex.Message, ex);
            return null;
        }
    }
}

 

I'd have switched XmlService with KeyLevelCacheService, XmlDocument with T, and LoadXml with Func<T>, then have a separate XmlService use KeyLevelCacheService internally.

2008 Aug 23

Lockers dictionary

tagged as: architecture | c#
Situation:
  • Your application aggregates data from external sources (say XML data returned via Http)
  • You want to cache such data locally, say up to an hour
  • You have some processing mechanism going over the cached data, using multiple threads

 

Problem:

A thread looking for an item in the cache to find that it's not there, would issue the http request to fill the cache. A second thread might want to initiate another call if it needs the data before the first thread has updated the cache.

 

 

Solution 1:

use locks on the cache object.

problem with that: you lock the whole cache, so other threads looking for a different type of data will be blocked, even though it's okay for them to get data from the cache, and even to insert data with a different key into the cache.

 

Solution 2:

Keep a key per requested entry.  Now you only lock what needs locking.

You'd keep a dictionary of lockers ( new object() ), then the action of obtaining a locker will cause a full cache lock, however the lock duration will be short (the time it takes to retrieve an object from a Hashtable, or to new an object and put it in the Hashtable), and then the long out-of-process operation of loading the object will be with a lock on the specific key, while the rest of the Cache is accessible for reads and writes by other threads.

 

Note - this is notepad (or rather WindowsLiveWriter) code. You'd need to fix syntax errors, and inspect the usage. License is MIT - Use at your own risk, and don't forget to attribute it to the writer

 

class KeyLevelSafeCache

{

IDictionary lockers = new Hashtable();

 

IDictionary cache = new Hashtable();

 

object ObtainLockerFor(string key)

{

return thread-safely-get-an-object-from-lockers-hashtable()

}

 

public T Get<T>(string key, Func<T> load())

{

var locker = ObtainLockerFor(key);

//now retrieve the object from the cache using 'locker'

}

}

 

2008 Aug 23

FactorySupportFacility gotcha

tagged as: tools | castle

The FactorySupportFacility in Windsor is very useful but there's a little something to be aware of when using it.

 

What is it?

This facility allows you to tell the container that when a given service is to be resolved, instead of new-ing it, it should call a factory method to obtain an instance.

This is very useful for context objects (like DbContext, HttpContext etc.) , which are usually being supplied by a framework thus you can't have the container instantiate them directly.

So, assuming you want to inject a ISomeContext object into a service, you need to create a factory that can obtain it for you:

public class SomeContextFactory

{

ISomeContext ObtainFromFramework()

{

return SomeFrameworkContext.Current; //or whatever

}

}

 

then you can setup the container to use that factory when injecting the context

 

The usage:

Online examples:

  1. http://www.jroller.com/hammett/entry/castle_s_factory_facility
    (using XML config, and it's somewhat old - that's the first announcment of this facility from Hammet back in the mesosoican era).
  2. http://mawi.org/ProgrammaticCastleMicrokernelWindsorAmpTheFactoryFacility.aspx
    (using programmatic container initialisation).

 

And, the gotcha:

When taking the programmatic road, you must follow this order of doing things:

  1. Create the facility instance:
  2. var facility = new FactorySupportFacility();
  3. Add it to the container
  4. container.Kernel.AddFacility("factory.support", facility);
  5. Register your factories in the facility:
  6. facility.AddFactory<ISomeContext, SomeContextFactory>("some.context", "ObtainFromFramework");

If you mix 2 and 3, it would break.

There reason of course is that registering the factory into the facility, mean that the facility needs no know about the current container and kernel. This is being done in step 2 so you simply can't do step 3 before that.

2008 Aug 12

Business requirements are bullshit

Not tagged yet

yippee - Steve Yegge has published a new post, which is always a treat to read.

This time, I was delighted enough simply by reading the title: Business requirements are bullshit

 

And that's after my wife has just returned from work, doing as part of a S.A.P. team, some massive blue-prints work.  Ha ha.

2008 Aug 7

On google insights - do numbers always count?

tagged as: tools | alt-net-israel

A dude on the ALT.NET Israel mailing list has given the new Google Insights a few things to chew on.

 

For example, he's shown that  there is much more interest in ASP.NET MVC over MonoRail.

 

So a wonder came up, whether one should choose a framework or a technology should it be highly searched for.

 

my take on the matter:

  • even if many people have searched for A, they might have found it, and decided against it.
  • even if many of them do like or work with A, it doesn't mean it's right for me.

 

I'd look for this type of people in the tech community.

People that:

  1. Are very professional, highly skilled, ones I do want to get help from;
  2. Have shown interest in helping the community, rather than asking questions.
  3. Can, on top of answering questions and giving advice, fix and improve the said technology themselves or using my suggestions/patches on the spot thus improving my productivity

 

No matter how you'd turn the search statistics, based on parameter 3 only, any OSS will be way ahead a closed source solution.

 

Gustavo Ringel also had a say:

I see a lot of articles about how to do stupid things with typed datasets, and much less about how to do great things with ORM's...should i had go for typed datasets instead of NHibernate or other ORM because i have more help of less skilled people?

2008 Aug 6

Skype addon for FireFox has killed Google Maps

tagged as: tools

I'm a big fan of google maps. A simple and yet very effective tool. I wish they had maps for Israel too ...


 

Anyway, I noticed today that the maps do not load on my FF. started disabling addons one by one (you'd usually blame FireBug ...) but I found out that it was the skype plugin's fault.

 

hmm. Im not really using it much anyway, and for the rare cases I do need to phone someone abroad, I guess I'll copy and paste into skype.

2008 Aug 3

How Did I Get Started In Software Development?

tagged as: miscellanea | personal

I've been tagged by Mike Hadlow (Great blog - subscribe to it now, what are you waiting for?)

 

Ok, let's go.

 

How old were you when you first started in programming?

My dad is one the IT dinosaurs. He have been doing the Punched card dance from early stages of public sector computing in Israel, and I guess I must have inherited the passion for programming. Before I got six, he bought me a ZX-Spectrum, alongside some BASIC beginners book in Hebrew and threw me into the deep water.

After a few months of getting comfy with the language, I've learned to read English and got my first serious programming book, one the tried to teach things like code reuse using GOTO and GOSUB.

I also had to learn some Assembler as the ZX's BASIC was pretty much limited.

zx_spectrum

 

 

What was your first programming language?

BASIC, as noted above

BASIC

 

What was the first real program you wrote?

A simple yet effective word processing application, written in Turbo Pascal 5.5. I was about 16 then.

This word processor was for the sole purpose of aiding my older sister go through Law School. I needed a way to type and printing her seminars and there was no built in WP in MS-DOS but edlin.exe back then, and no Internet to download a WP from.

 

At 18 I wrote another program in Pascal, aimed at keeping track of membership payments for a local Bnei-Akiva Branch. I learned the hard way that building a DB engine by hand without any theoretical background, and without ever hearing about terms like "SQL", "Relations", "Transaction" and the like, is not a simple thing to do. By the time this application had enough features I have already left to recruit to the IDF, so it never got into production.

turbo_pascal

 

Then there was a gap of a few years during which I didn't program until I was 24, and I needed to write my third and forth applications. They were in ACCESS, VBA and VB, written as part of my jobs in the army as a logistics officer. I needed a better inventory manager than the old MAGIC based that my unit had, and a better solution for keeping track of vacations utilisation of the staff.

 

There you go. Not only the first one, but the first four.

 

 

What languages have you used since you started programming?
  • On non-paid projects (including University) I worked with BASIC, Assembler, C, Turbo Pascal 5.5, FORTRAN, COBOL, VB6/VBA, Java, 8086 Assembler, ADA, PROLOG and C++.
    Is LOGO a language?
  • Languages I used for paid projects/employment (ORDER BY FrequentlyUsedFactor):
    C#, Javascript, Boo, ActionScript, VBA, Ruby, Python
  • I am a certified J2EE developer as stated on a paper I got from Oracle University or whatever they're called. I Must admit that OC4J was the single most annoying development environment I've ever seen.
  • Languages that I wish I to use for a real project: F#

 

What was your first professional programming gig?

After leaving the army, I taught myself C#, HTML and ASP.NET, registered as self employed and ran a few projects for a few clients. The first of which was a simple VBA based automation for an import/export dealer in the aviation industry. The application was automating the read of RFQ emails, looking up for matched data in their propriety Interbase driven DB, and then exported a report containing highly probable sale items. They liked it so much that they started adding features, and other business-helping apps. They still are a valued customer.

An interesting note here - the last time I have updated or fixed a bug on the first application was almost two years ago. And it's still in daily use, so even though it's coded in a way I'd call blasphemy today, with all the VB-ness scattered around, I still am very proud of this piece of code, as professionally it is rock solid, and not too difficult to maintain, and from business prospective it had a huge benefit for the client.

 

 

If you knew then what you know now, would you have started programming?

I would have started even earlier :)

 

 

If there is one thing you learned along the way that you would tell new developers, what would it be?

Be open to criticism. If you program alone, then try to share as much code with the community as you can, by participating in open source projects. The best place to learn is from your own mistakes, pointed out by others.

I can certainly testify on myself, that I've learned a lot more when I was part of teams where I was not THE tech leader, be it on paid gigs or on OSS.

 

 

What's the most fun you've ever had programming?

During University when I took "Introduction to Algorithms" (learning part I of "Introduction to Algorithms") I had to build a Red-Black tree representation. Back then The only language I know well enough was VB, but I had write it in C++. I did know the basic syntax from my C background, and some vague knowledge of pointers and memory allocations, but that's about it. The project was supposed to be written by a team of three, but I then decided that I had to learn C++ decently and write this alone, so I sat down for a long weekend, got myself a copy of the STL to learn by example, and produces a working generic RB-Tree implementation using Templates to allow generic keys in the tree.

When I sent it over to the other team members, all they had to do was to smoothen up the rough edges.

Again, it wasn't very pretty, but I did prove a point to myself, with that little exercise.

 

Who am I calling out?

In order to make the propagation of this topic even faster, I decided to tag 9 people (!):

  1. People I've just randomly picked up from my blogroll:
    Andre Loker, Damien Guard and Symon Rottem
  2. Bloggers that are definitely not posting enough, so they probably haven't posted about the issue yet:
    Oren Ellenbogen and Justice Gray
  3. The long shot *:
    John Lam, David Heinemeier Hansson (DHH), Steve Yegge and Joel Spowlsky

    * high profile dudes that I like to read about their programming cradle, but are most probably not reading my blog -> hence the length of the shot
2008 Aug 3

ALT.NET Israel conf update

tagged as: alt-net-israel

Due to the large volume of participants, we needed a larger venue.

Sela Group has generously agreed to accommodate the conference in their building.

 

So, see you there this Thursday at 18:30

 

 

2008 Aug 1

Feedback please

tagged as: personal

One of the goals of this blog is for me to be able to get feedback from other people. Usually it means feedback regarding code I write, design decisions I make, and other technical stuff.

However one other goal is to improve my written English skills. Therefore I would be happy to accept any input regarding spelling, vocabulary and grammar mistakes. I won't be offended, that's a promise.

2008 Jul 31

STT - Extra comma in collection initialisers and enums

tagged as: c#

You all know what STL is (ok, not all of you, some have skipped C++ altogether and some have only created a few Carnivore/Herbivore classes for Uni).

 

But you don't know what STT is.

Well I'll tell you, just sit nicely and listen.

 

STT is "Silly Tip & Trick".

 

This is one:

 

 
The Extra comma STT

You probably already know of the collection initialiser syntax introduced into C# 3.0:

stt_comma 1

At times, you'd have a long list of items in the initialiser, and you find yourself doing copy&pastes to add lines, or removing lines from the list. There's this little extra step you need to do, that is making sure that you have a comma between any two adjacent lines.

That makes the copy&paste a bit annoying.

stt_comma 2

However, it appear that csc.exe would accept an extra trailing comma at the end of the list, so this code is 100% valid:

stt_comma 3

Now it's easier to text-manipulate the list.

 

 

It also works for Enum declarations:

stt_comma 4

 

So, even though having three cats in the house is busy enough, as far as c# is concerned I can easily add more of these. Not sure what the existing cats would think of that.

 

Just to make sure it actually works:

stt_comma 5

 

 

 

curiosities:

  1. Envy code R rock.
  2. I use red background for my elevated CMD window
  3. For the Visual Studio only dudes: csc.exe is the c# compiler bundled as part of the .NET runtime install.
  4. yes, I sometimes use edit.exe
  5. Envy code R rock.
2008 Jul 30

On babies, entities, controllers and confidence votes

The Sharks

Here in Israel, there's a reality/documentary TV show called "The Sharks".

It's about people who have some kind of a business idea, and are looking for investors.

Each entrepreneur gets a few minutes to present their idea and business plan in front of 4-5 well-known Israeli businessmen, trying to get their support in return for percentages of their project.

One can differentiate the totally bad projects with possibly OK projects, simply on the basis of a proper preparations. Some projects are simply vague ideas that popped up on someone's head, without any business plan of any kind.

 

Then you have the projects that comes with a detailed business plan, market research, pricing policies and what-not. These are of course the ones that the Sharks (potential investors) show interest in. The interesting bit is that most of the times, instead of asking strictly business related questions, they tend give more importance to the actual usability of the proposed product/service/whatever. They try to get in the head of the potential consumers and look for Achilles' heels from the user's point of view.

 

 

Solving consumer problems

The point is, that you cannot create a product or service to solve problems that you think that people have. You have to solve actual problems that potential consumers are facing.

 

Paraphrasing DHH from a presentation lately, "It's not Rocket Surgery". You should simply solve people's problems, otherwise they won't be interested.

 

 

self consumer

Who is the better consumer than yourself?

Example: There's this person I know, who will sell you baby carriers. They look very simple in first glance, but then you see that it's actually pretty useful - it's adjustable, you can re-use the same carrier in several carrying positions (low, high, front, back), and it's comfortable for parent and baby. The thing is - she didn't wake up one day with a crazy idea, hoping it'd match someone's needs. She made one for herself and her baby, making it better with time, and then thought - 'hey someone else might like it'

Going back to DHH and his presentation, he states there clearly that the whole RubyOnRails thing was simply something he needed for his day job, so it became very useful, as the consumer (himself) was giving him direct feedback during the development process.

Same can be said on many OSS projects, like NHibernate, the whole Castle stack and many more.

I can testify on AspView, which I created to make my day job easier and more fun, as I disliked WebForms and my employer insisted on ASP.NET and C# all around - that was my best shot. I got immediate feedbacks from the consumer (myself and my team members) so it stayed focused on solving consumer needs.

 

 

Demonstrate trust in your tools

You should be trustworthy. I evangelise the use of good tools, and I name the Castle stack, NHibernate, Rhino Commons, and more as good tools. I can do this whole heartedly since I use these very tools for my day jobs, on paid projects, not only for pet projects.

 

 

And if you are not a consumer

Take ASP.NET MVC. This project is being internally run by a team of developers, who their day job is to build this tool, not to use it. On the surface it presents a major problem, no consumer feedback.

The way they chose to solve this problem was pretty simple. Expose as much as you can to the public. Push potential users to play with the API, experiment with use cases, build extensions, whatnot. Continuously grab community input, incorporate it in the product, and get new feedback. All that has started from the earliest stages by ScottGu, then Phil Haack. The while team seam to be everywhere, from mailing lists to ALT.NET conferences, getting consumer input and building around it.

The outcome is that they can focus on solving consumer problems, and the progress of improvements is amazing. It got to the point that I have no problem at all with using ASP.NET MVC, even though I'm an active member in MonoRail. Personally I prefer MonoRail, but I really see ASP.NET MVC as a viable option, and recommend it as a possible solution.

 

 

Opposite examples

Take the Entity Framework. I've been hearing about this beast from 2005. However being able to get the feel of it took way too long. Meanwhile it appear that a lot of stuff has been introduced into it, that might not even be interesting to consumers, while rendering fixing the consumers' problems more difficult.

 

And as for trusting your own tools - I've heard once that Visual Source Safe was never used internally for development within Microsoft. I also don't really believe that there is a single public major website under Microsoft's umbrella that uses SqlDataSource, heavily customised GridView components and other widely demo-ed Webforms stuff.

 

 

Confidence

Technologies like Silverlight, ASP.NET MVC, not to mention the more experimental stuff like IronXYZ and F#, find their way into community review, and even to internal production use. Microsoft are voting confidence in these products, so do I.

 

 

ALT.Microsoft

So as far for the notorious Vote of No Confidence in EF, I never have joined it as it simply make no sense imo. It simply does not interest me enough to even vote. They way I see it, EF belongs next to WebForms, while MVC/IronXYZ/F#/etc are legitimate ALT.NET

 

 

Cuz ALT.NET is not about opposing anyone. Definitely not MS - hey these guys brought us the CLR and BCL.

It's also not about being the freedom guerilla fighters fighting the evil Corporate. Not at all.

 

I think that ALT.NET is a great idea, just like XP (Extreeme Programming), and like XP it has a bad name, as it implies 'niche', 'alternative', 'scary', 'elitist', 'vane'.

 

It's not.

 

It's about good tools, built to help make us developers work better, and have more fun during. Parts of the DevDiv are as ALT.NET as it gets.

2008 Jul 28

Unique when not null (or not empty) in SQL Server

tagged as: SQL Server

In SQL Server, you have two main types of Indexes, one that allow duplications, and one that does not.

However, if you want a rule like "I want to forbid duplications, except for null values" you do not have a built in feature for that, as the unique index will treat the NULL value as a real value, thus allowing up to a single row with that NULL.

 

Apart from refactoring the DB schema, the solution I usually was doing has been to create a trigger to deal with that:

 

CREATE TRIGGER dbo.People_Unique_NonNull_Email
   ON  dbo.People
   AFTER INSERT
AS
BEGIN
    SET NOCOUNT ON
    DECLARE @Count INT
    SELECT        @Count=COUNT(p.Id)
    FROM        People p
        JOIN    INSERTED i On i.Email = p.Email
    WHERE        i.Email IS NOT NULL
    IF @Count > 0
    BEGIN
        RAISERROR ('Cannot put a duplicate email on People table', 16, 1)
        ROLLBACK TRANSACTION
    END
END
GO

 

However, Moran Benisty, my T-SQL Ninja pal, has pointed out that the SELECT and IF might bit a wee bit apart, and revised this to

CREATE TRIGGER dbo.People_Unique_NonNull_Email
   ON  dbo.People
   AFTER INSERT
AS
BEGIN
    SET NOCOUNT ON


    IF EXISTS(SELECT 1
        FROM        People p
            JOIN    INSERTED i On i.Email = p.Email
        WHERE        i.Email IS NOT NULL
    )
    BEGIN
        RAISERROR ('Cannot put a duplicate email on People table', 16, 1)
        ROLLBACK TRANSACTION
    END


END
GO

 

I'll leave adding the UPDATE case to the readers

2008 Jul 27

Unit Testing in PROLOG - take 2

tagged as: personal | Testing

I've refined my "unit testing framework" a bit, to make it less awkward.

 

the code:

test(Fact/Test):-
    current_predicate_under_test(Predicate),
    retractall(test_def(Predicate/Fact/Test)),
    assert(test_def(Predicate/Fact/Test)).
 
setup_tests(Predicate) :-
    retractall(test_def(Predicate/_/_)),
    assert(current_predicate_under_test(Predicate)).
 
end_setup_tests:-
    retractall(current_predicate_under_test(_)).
 
run_tests :-
    dynamic(tests_stats/2),
    bagof(P/Tests, bagof((Fact/Test), test_def(P/Fact/Test), Tests), TestsPerPredicate),
    run_tests(TestsPerPredicate, Passed/Failed),
    write_tests_summary(Passed/Failed).
 
run_tests(TestsTestsPerPredicate, TotalPassed/TotalFailed) :-
    run_tests(TestsTestsPerPredicate, 0/0, TotalPassed/TotalFailed).
 
run_tests([], Passed/Failed, Passed/Failed):-!.
run_tests([P/Tests|Rest], Passed/Failed, TotalPassed/TotalFailed):-
    write('testing '), write(P),
    foreach_test(Tests, PassedInPredicate/FailedInPredicate),
    write(' passed:'), write(PassedInPredicate),
    (FailedInPredicate > 0, write(' failed:'), write(FailedInPredicate) ; true),
    nl,
    Passed1 is Passed + PassedInPredicate,
    Failed1 is Failed + FailedInPredicate,
    run_tests(Rest, Passed1/Failed1, TotalPassed/TotalFailed).
 
foreach_test(Tests, Passed/Failed):-
    foreach_test(Tests, 0/0, Passed/Failed).
 
foreach_test([], Passed/Failed, Passed/Failed):-!.
foreach_test([Fact/Test|Rest], Passed/Failed, NewPassed/NewFailed):-
    assert((run_test:-Test)),
    (
        run_test, !,
        NextPassed is Passed + 1,
        NextFailed is Failed
    ;
        NextFailed is Failed + 1,
        NextPassed is Passed,
        write('FAIL: '), write(Fact), nl
    ),
    retract((run_test:-Test)),
    foreach_test(Rest, NextPassed/NextFailed, NewPassed/NewFailed).
 
write_tests_summary(Passed/0) :- !,
    nl,
    write(Passed), write(' tests passed :)'),
    nl.
write_tests_summary(Passed/Failed) :-
    nl,
    write(Passed), write(' tests passed, however'), nl,
    write(Failed), write(' tests failed :('),
    nl.
 
reset_all_tests:-
    retractall(test_def(_/_/_)).

 

the usage:

:- setup_tests('conc/3'). 

:- test('empty and empty returns empty'/(
    conc([], [], [])
)).
:- test('empty and nonempty returns L2'/(
    conc([], [1,2], [1,2])
)).
:- test('nonempty and empty returns L1'/(
    conc([1,2], [], [1,2])
)).
:- test('nonempty and nonempty returns L1 concatenated with L2'/(
    conc([1,2], [3,4], [1,2,3,4])
)).
:- end_setup_tests.

 

my current test output:

| ?- run_tests.
testing conc/3 passed:4
testing create_list/3 passed:2
testing empty_pit/5 passed:1
testing get_opposite_pit/2 passed:2
testing in_range/2 passed:2
testing is_in_range/2 passed:4
testing put_seeds/5 passed:3
18 tests passed :)
yes
2008 Jul 25

Laptop advice

tagged as: miscellanea

I've been looking at getting a new laptop lately.

Currently my options are:

   Dell Latitude 830 (15")

   Dell XPS 15"

   Sony Vaio CR (14.1")

 

I'll probably go for a 8300/7500 cpu.

Centrino 2 rigs on Sony site are only for 13" and 16", and I've seen none on Dell's site

 

 

My main concern is with the clarity of the screen.

I am very happy with my Toshiba screen (Tecra A3 15", matt, 1024X768).  I don't like the new trends of high resolution (tiny fonts) and glossy screens (I want to see my code, not my face. I'm too damn pretty - it's distracting).

 

Any input is welcome

2008 Jul 24

"But it's using reflection, so it must be slow"

tagged as: architecture | nhibernate

Well, not *that* slow apparently.

 

The lesson:

Don't be afraid of powerful tools.

You can use reflection right, gain the power, while not losing too much performance.

 

Quoting from nhusers mailing list:

How much you be scare about the use of reflection in NH if 1.000.000 of access to get & set to a field mean 0.2seconds ?
--
Fabio Maulo

2008 Jul 24

Unit testing in PROLOG

tagged as: personal | Testing

Finally I'm sitting down to be done with my Computer Science degree. I've been studying in the Israeli Open University starting 2003, while working full time and more. Over than two years ago I reached the point of having literally no time at all to finish it up, so I left it to be with only two final projects to complete, present and defend.

The first one is to write a simple AI enabled game (using depth delimited alpha-beta algorithm variation) , in PROLOG.

 

Back when I took that course, the whole paradigm was too strange to me. I've been doing procedural and OO coding for years, and the look of the programs just looked ....  wrong.

Nowadays that I developed a lot of curiosity into declarative languages like Erlang and F#, (and being a much better and way more experienced developer) I can relate to that type of coding more easily.

 

So, dusting the rust of two year of not touching it at all, I sat down today to start working on that project (delivery is next month), I started with writing down a small helper for running unit tests on my code.

 

Ain't pretty, but it serves both the need to test my code, and the need to re-learn the language:

 

run_tests  :-
    dynamic([
        tests_passed/1,
        failing_tests/1,
        total_tests_passed/1,
        total_failing_tests/1 ]),
    assert(tests_passed(0)),
    assert(failing_tests([])),
    assert(total_tests_passed(0)),
    assert(total_failing_tests([])),
    bagof(
        (Module/Predicate, Tests),
        tests(Module/Predicate, Tests),
        TestDefinitions),
    run_tests_definitions(TestDefinitions),
    retract(total_tests_passed(TotalPassedAtEnd)),       
    retract(total_failing_tests(TotalFailedAtEnd)),
    len(TotalFailedAtEnd, TotalFailedAtEndCount),
    write('summary:'), nl,
    write('Passed: '), write(TotalPassedAtEnd),
    write(' Failed: '), write(TotalFailedAtEndCount), nl, nl,
    (TotalFailedAtEndCount> 0, write_fails(TotalFailedAtEnd) ; write('Alles Gut'), nl).

run_tests_definitions([]) :- !.
run_tests_definitions([(Module/Predicate, Tests)|T]) :-
    write('module: '), write(Module),
    write(' predicate: '), write(Predicate),
    write(' ... '),
    run_tests(Tests),
    retract(tests_passed(Passed)),       
    retract(failing_tests(Failed)),
    assert(tests_passed(0)),
    assert(failing_tests([])),
    len(Failed, FailedCount),
    write('Passed: '), write(Passed),
    write(' Failed: '), write(FailedCount), nl,
    retract(total_tests_passed(TotalPassed)),       
    retract(total_failing_tests(TotalFailed)),
    NewTotalPassed is TotalPassed + Passed,
    conc(Failed, TotalFailed, NewTotalFailed),
    assert(total_tests_passed(NewTotalPassed)),       
    assert(total_failing_tests(NewTotalFailed)),
    run_tests_definitions(T).

write_fails([]) :- !.
write_fails([H|T]) :-
    write_fails(T),
    write(H), write(' failed'), nl.

run_tests([]) :- !.
run_tests([H|T]) :-
    run_test(H),
    run_tests(T).

 

run_test(Test) :-
    call(Test),!,
    tests_passed(X),
    retract(tests_passed(X)),
    NewX is X + 1,
    assert(tests_passed(NewX)).
run_test(Test) :-
    failing_tests(X),
    retract(failing_tests(X)),
    NewX = [Test|X],
    assert(failing_tests(NewX)).

% Asserts
assert_all_members_equal_to([], _).
assert_all_members_equal_to([H|T], H) :-
    assert_all_members_equal_to(T, H).

 

this code is allowing me to define my tests like the following:

tests(moves/change_list, [
    change_list__add_first__works,
    change_list__add_middle__works,
    change_list__add_last__works,
    change_list__empty_first__works,
    change_list__add_middle__works,
    change_list__add_last__works
]).
change_list__add_first__works :-
    L = [1,1,1],
 
change_list(L, L1, 1, add),
    L1 = [2,1,1].
 
change_list__add_middle__works :-
    L = [1,1,1],
 
change_list(L, L1, 2, add),
    L1 = [1,2,1].

 

...

 

invoking the tests is as simple as the predicate:

:- run_tests.

 

and the current output from my project is:

module: utils predicate: in_range ... Passed: 4 Failed: 0
module: utils predicate: create_list ... Passed: 2 Failed: 0
module: moves predicate: change_list ... Passed: 6 Failed: 0
module: moves predicate: move ... Passed: 1 Failed: 0
module: moves predicate: step ... Passed: 1 Failed: 1
summary:
Passed: 14 Failed: 1
step__when_ends_within_same_player_pits__works failed
yes

 

Ahm. A failing test .... back to work I guess.

 

btw, The game I am implementing is Kalah.

2008 Jul 21

Patch management approaches using decent CSM

tagged as: tools | Source Control

Following Ayende's post on Patch management approaches using centralized SCM, here are how I would have dealt with the 4 issues that he brings up, using a Decentralised SCM.

 

I use git, so I'll use git terms here. I guess it's quite similar for other DSCM systems.

 

Note that I haven't used patches on git development as until now all of my git work was on repositories I had write access to, However the principals are the same (i.e. - all of the tree is local to my machine, thus I can reach any point in the history locally).

 

First I'll clone the hosted repository to my local machine.

  • #1
    I'd have created a separate local feature branch for each feature, so separating the patches is easy
  • #2
    again, I can do this in two separate local branches, so I do not need to "revert and apply" when I move between the two. I also get to have a complete SCM experience, not only a single patch/step per feature.
    I can also have a third branch, combining the work of the two feature branches, for my own use
  • #3
    the second feature's branch would be based on the first one. should the first need some rework that is important to the second, it'd be easy to apply changes on the first, then rebase the second ontop of the updated first
  • #4
    just two commits on the same branch.

So, using a DSCM, I can work locally with the benefits of a SCM, have as many branches/features as I want. the whole tree is stored locally, and its blazing fast to switch branches, so I can easily work on every aspect I want, and easily create a patch from every node in the history tree, to send to the project owners.

2008 Jul 19

MonoRail sample gone AspView

tagged as: castle | monorail | aspview

Some more AspView love:

This dude, Morten Lyhr (great blog - go on and subscribe), has taken the sample MonoRail Getting Started project and AspView-ed it.

 

Take a look.

2008 Jul 16

I didn't brake the build

tagged as: castle | monorail | aspview

After making it build locally and reaching the conclusion that AspView builds correctly as part of the main Castle build , I've commited the changes to the repository, and the build server appear to agree with me:

Build_Succeded_on_the_build_server

Subscribe

Statistics

300
483

Related Books

Related Jobs

Related Ads

search page | Blog's home | About me