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.
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.
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.
can you guess why this makes me happy?
This is the output of building Castle's trunk, both for .NET 3.5 and .NET 2.0, after inserting AspView into the core project. Took me a while as I had to:
So, soon enough (hopefully by the end of this day) you'd be able to see AspView on the build server.
Thx again for all of the users and patch-contributors for your faith in this library.
Following many other good fellas, (like Scott Hanselman, Damien Guard, Phil Haack, Justin Angel and many more), one more has joined Microsoft.
Hamilton Verissimo, the founder of Castle Project, and an inspiration to myself and many others, would most probably serve as another great power in the DevDiv, which appear to be an awesome place to work at, more and more every day.
Way to go Hammett.
A cute programming languages quiz.
It'd show you 12 snippets of code, and you'd have to guess the programming language the code is written in.
If you have only started coding in the late 90's then you're in trouble.
heck, even if you have started on late 80's. I mean, really.
As I've been exposed to programming from a very early age, on the first half of the 80's, and my father being and old time punching-cards hacker, and I also tend to reach for the new stuff these days, I managed to score a nice rounded 12/12 100 points.
Can you?
It's on "First in first served" basis, and there is a limited capacity, so go ahead and register at the conference page:
You'd need an openid identity in order to register. If you don't have one, that's be a great opportunity to get yourself one. it's free, and it's gaining more and more popularity as a SSO mechanism for the web. I'm using myopenid.com - signing up was simple, easy and fast.
IMPORTANT:
Please do not register, just because of the free admission if you don't think that you'd come. Otherwise you'd be taking a place of someone else's.
If you do register and later on find out that you won't be able to take part, please contact us organisers so we'd be able to add people from the waiting list.
if you blog - go ahead and spread the word.
if you can - tag it with "alt-net-israel" and/or "altnetconf" so it would propagate to the aggregators.
cya there
I'm really pleased to announce that there is going to be an Alt.Net conference in Israel, namely Alt.Net.Israel.
If you haven't heard of Alt.Net yet, read David Laribee's post to better understand the term - What's ALT.NET
The conference will be held on Thursday 7th and Friday 8st August 2008, at the SQLink offices in Ramat Gan, and is being organised by Roy Osherove, Oren Eini (a.k.a Ayende), and myself.
Thursday 7th, at 18:30-20:30: planning meeting, following a walk to a nearby pub or coffee shop to socialise.
Friday 8th, at 09:30-16:30: sessions.
We have chosen a summer Friday and a super accessible location on purpose, to give the religious people a chance to attend and still make it on time home for Sabbath.
That is really up to the people who attend. We will be following an open spaces format, similar to the other alt.net conferences in the UK, USA and Canada, where the agenda is decided by the conference participants. Anyone can lead sessions on particular topics of interest, participate as an attendee or just hang around and chat with interesting people.
Please note that registration is not open yet! I will blog more when we have information on this, hopefully it will open shortly. I can say that the conference will be free of charge.
If you have any questions, please feel free to contact us. I'm really looking forward to this, should be a great event!
See you there :)
P.S, also a big thankyou to Ben Hall, of the alt.net UK organisers, which is partly responsible for my enthusiasm for alt.net conferences, and I've also used his previous announcement as a template for this one ...
Serving as a mental note, and as a service to dear readers who hadn't been bitten by this yet.
javascript's parseInt method is not the same as .NET's int.Parse.
there's this 'radix' argument which is meant to tell the parseInt method whether we want to treat the string we parse as binary, octal, decimal, hexadecimal or whatever.
Now the naive programmer (a.k.a. myself) would think that the default is always base 10, so parseInt(x) === parseInt(x, 10) for every x.
Apparently parseInt tries to outsmart us, and it's actually guessing the radix if not set. so if x begins with 0x, it would guess hexadecimal, and if x begins with 0 it would guess it's octal.
so, parseInt('010') === parseInt('010', 8) === 8
ok, I can live with that maybe.
however it would also 'guess' that 09 is octal (even though 9 is not an octal digit !) thus parseInt('09') === 0
I found this by chance, when a Date.parse method I have was parsing "09/07/2008" into a date-info object with day==0, causing it to fall back into today's date
So, the lessons we've learned today:
So after moving to Vista last week, I've tried a full castle build with tests.
Things I had to take care for it to run properly (from easy to not-as):
Now that I have a way to run the build and make sure all tests pass, I can start working on my next Castle assignment - bringing AspView into the core project, but that's a whole other post so keep your RSS reader open ...
My poor old laptop has had a lot of problems lately, priming at ignoring any network connection yesterday and having many problems with svn and git sessions when the network was on, so I decided to re-install.
'twas 1am, so I thought 'what the heck - let's try this vista thing at last'.
It was surprisingly a smooth experience. The initial setup identified almost all of the drivers, but the sound-card and the SD card reader. However, the auto updates (which took over an hour cuz there was apparently a lot to update) took care of the sound, and I got the SD driver from Texas Instrument's site.
What I had to install to make the machine workable for day-to-day work:
still missing (no time) but essential:
btw, since I've installed VS2008 without going 2005 first and without the full SDKs, I ran into a problem with NAnt 0.86b1 - complaining about missing .NET 2.0 stuff. It appear to be a known bug in NAnt, that has been fixed back on late 2007, so I've just switched to a nightly build of 0.86b2 and the problem did go away. I need to make sure that it won't affect my Castle build.
Didn't have much to say here. I consider it a test post (see if Writer will work from Vista) but it beats the crap out of "TEST POST PLEASE IGNORE" ...
Lately I've been asked about doing FTP related stuff in .NET .
There appear to be many "Ftp Clients" out there on CodeProject and other sites.
I really don't get 'em.
They are simple a leaky abstraction on top of straightforward BCL classes.
So what my solution is?
1: public void Upload(string server, int port, string targetFolder, string fileName, string username, string password, bool isActive)
2: {
3: var url = string.Format(
4: "ftp://{0}:{1}{2}/{3}", server, port, targetFolder, fileName)
5: using (var ftp = (FtpWebRequest)WebRequest.Create(url))
6: {
7: ftp.Credentials = new NetworkCredential(username, password);
8: ftp.KeepAlive = false;
9: ftp.UseBinary = true;
10: ftp.Method = WebRequestMethods.Ftp.UploadFile;
11: if (isActive)
12: ftp.UsePassive = false;
13:
14: using (var writer = new BinaryWriter(ftp.GetRequestStream()))
15: writer.Write(File.ReadAllBytes(fileName));
16: }
17: }
This basic notepad code covers most of the functionality in FtpWebRequest. You can easily set Binary/ASCII, Active/Passive, Credentials and whatnot.
Alternatively, in some cases you can just spawn a ftp.exe process with a simple ftp script. Anyway you can rid yourself from unneeded leaky abstractions.
Following Scott Hanselman's post on FileUpload in ASP.NET MVC, I'll add here a few bits on doing that in MonoRail.
First, as MonoRail is an extension on top of plain ol' ASP.NET, just as ASP.NET MVC is, you can do the exact same thing - i.e iterate over Request.Files, and use a mocked Files collection for test or something.
But as the action parameters binder is very smart, and easily extensible, it's even nicer to just bind the posted data to a HttpPostedFile, using a FileBinder:
1: [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
2: public class FileBinderAttribute: Attribute, IParameterBinder
3: {
4: public int CalculateParamPoints(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
5: {
6: var key = parameterInfo.Name;
7: return context.Request.Files[key] != null ? 10 : 0;
8: }
9:
10: public object Bind(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
11: {
12: var key = parameterInfo.Name;
13: return context.Request.Files[key] as HttpPostedFile;
14: }
15: }
So a custom binder is an attribute, that implements IParameterBinder, a two methods interface:
so now you're action can look like this:
1: public void Save([FileBinder] HttpPostedFile myfile)
2: {
3: if (myFile != null)
4: {
5: // do stuff with the file
6: }
7: }
Cool? well actually what really is cool is that binding to HttpPostedFile is baked into MonoRail to begin with - so you don't even need this FileBinderAttribute at all ! you can simply
1: public void Save(HttpPostedFile myfile)
2: {
3: if (myFile != null)
4: {
5: // do stuff with the file
6: }
7: }
So why did I show you that?
Testablility.
Since HttpPostedFile is not easily mockable* (cuz it's bloody sealed and not new-able), you should do what you always do when in need to bypass one of these un-testable hard-to-test* sealed classes: Adapter pattern. Introduce IHttpPostedFile, and supply your own HttpPostedFile encapsulating the built in one.
so:
1: [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
2: public class FileBinderAttribute: Attribute, IParameterBinder
3: {
4: public int CalculateParamPoints(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
5: {
6: var key = parameterInfo.Name;
7: return context.Request.Files[key] != null ? 10 : 0;
8: }
9:
10: public object Bind(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
11: {
12: var key = parameterInfo.Name;13: var file = context.Request.Files[key] as HttpPostedFile;
14: return file == null ? null : HttpPostedFileAdapter(file);
15: }
16: }
and
1: public void Save([FileBinder] IHttpPostedFile myfile)
2: {
3: if (myFile != null)
4: {
5: // do stuff with the file
6: }
7: }
* Yes Roy, I know you can throw some TypeMock magic at it
DISCLAIMER:
If you are a potential client of mine, or rather a current one, please stop reading NOW, as it's one of these embarrassing "I am sometimes too stupid" posts.
Oh my.
That's how my 3am code can look like:
1: var page = filter.Page.GetValueOrDefault(1);
2: var pageSize = filter.PageSize.GetValueOrDefault(30);
3: var firstResult = (page - 1) + pageSize;
It's for NHibernate style paging (i.e. firstResult is for a 0 based index)
Spotted (thanks to DbAwareIntegrationTests) and fixed at 6pm
A quick ripoff from NHibernate's users group:
Fabio Maulo:
The base concepts to understand are (my opinion):
- *The Cache is not the panacea of performance.*
- Don't use the Cache like the base of your app; add the management of Cache at the end of your development process to increase the performance only where you really need do it.
- Implementing a method named GetAll is, in most cases, a bad idea; an acceptable mediation is PaginateAll(pageSize).
- InMemoryFilter can have less performance than filter trough RDBMS (especially when you intent to do it trough Cache with a large amount of entities).
- Take care on what happen to the memory usage of your app when you are using Cache.
Ayende:
The cache is not magic, and should not be treated in such a fashion. I refuse to use the 2nd level cache in my applications until I have a perf problem that can't be solved by creating smarter queries.
Think about the cache as band aid, and good design as avoiding the need for that.
And I say Hallelujahs
The tools (various small helper libraries) are now under http://svn.castleproject.org:8080/svn/castlecontrib/Tools/
what's in there:
I've been asked about it several times lately, so I'll just put here an oldie that I've been using for a few years now untouched:
1: // MIT license
2: // Copyright 2005-2008 Ken Egozi
3: //
4: // Permission is hereby granted, free of charge, to any person obtaining a copy
5: // of this software and associated documentation files (the "Software"), to deal
6: // in the Software without restriction, including without limitation the rights
7: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8: // copies of the Software, and to permit persons to whom the Software is
9: // furnished to do so, subject to the following conditions:
10: //
11: // The above copyright notice and this permission notice shall be included in
12: // all copies or substantial portions of the Software.
13: //
14: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20: // THE SOFTWARE.
21:
22: using System;
23: using System.Collections.Generic;
24: using System.Text;
25: using System.Security.Cryptography;
26: using System.Collections;
27:
28: namespace KenEgozi.CryptographicServices
29: {
30: public static class Hashing
31: {
32: private static Hashtable hashAlgorithms = Hashtable.Synchronized(new Hashtable());
33:
34: /// <summary>
35: /// Hashing a given string with SHA2.
36: /// </summary>
37: /// <param name="data">Data to hash</param>
38: /// <returns>Hashed data</returns>
39: public static string HashData(string data)
40: {
41: return HashData(data, HashType.SHA256);
42: }
43:
44: /// <summary>
45: /// Hashing a given string with any of the supported hash algorithms.
46: /// </summary>
47: /// <param name="data">Data to hash</param>
48: /// <param name="hashType">Hashing algorithm to use</param>
49: /// <returns>Hashed data</returns>
50: public static string HashData(string data, HashType hashType)
51: {
52: HashAlgorithm hash = GetHash(hashType);
53: byte[] bytes = (new UnicodeEncoding()).GetBytes(data);
54: byte[] hashed = hash.ComputeHash(bytes);
55: StringBuilder sb = new StringBuilder(64);
56: foreach (byte b in hashed)
57: sb.AppendFormat("{0:x2}", b);
58: return sb.ToString();
59: }
60:
61: private static HashAlgorithm GetHash(HashType hashType)
62: {
63: if (!hashAlgorithms.ContainsKey(hashType))
64: hashAlgorithms.Add(hashType, CreateaHashAlgorithm(hashType));
65: return hashAlgorithms[hashType] as HashAlgorithm;
66: }
67:
68: private static HashAlgorithm CreateaHashAlgorithm(HashType hashType)
69: {
70: switch (hashType)
71: {
72: case HashType.MD5:
73: return new MD5CryptoServiceProvider();
74: case HashType.SHA1:
75: return new SHA1Managed();
76: case HashType.SHA256:
77: return new SHA256Managed();
78: case HashType.SHA384:
79: return new SHA384Managed();
80: case HashType.SHA512:
81: return new SHA512Managed();
82: default:
83: throw new NotImplementedException();
84: }
85: }
86: }
87:
88: public enum HashType
89: {
90: MD5,
91: SHA1,
92: SHA256,
93: SHA384,
94: SHA512
95: }
96: }
Not beautiful, however useful.
You can download this file from here (just remove the .txt - the server doesn't serve .cs files directly)
btw, the colouring of the source was made with the help of http://www.manoli.net/csharpformat/, even though I had to do some manual tweaking to make it work with this blog. If colours of reserved words, comments etc. do not appear, then please refresh your browser's cache to get the updated css
I really don't need to add anything, right?
Installed it myself today. Appear to be a bit faster, and to eat up less memory.
The Google Toolbar and FireFTP were updated automatically.
I needed to manually re-install FireBug and IE-Tab
btw, does anybody know where did the Back and Forward buttons has gone to? Im using the keyboard usually, but sometimes (especially during in-office-lunch-time) I need to click the Back thing with the mouse
UPDATE: it appear that as part of the upgrade, FF3 has inherited my customised toolbars and that's why it was looking weird. So I right-clicked on the toolbar -> customise, the clicked "Restore Default Set". All the buttons came back, then I rearranged the toolbar to my liking.
An innocent question raised by Ayende has started an interesting debate on the comments.
In short (read it all there - don't be lazy)
Which interface name is better?
a. IRecognizeFilesThatNeedToBeIgnored
b. IIgnoreFilesSpecification
with a single method: ShouldBeIgnored(string file);
Some were in favour of a, some in favour of b.
The interesting thing is that many has offered a third option:
c. IFileFilter
Let's group these things:
Personally I couldn't care less which one of the first type will be used. I slightly in favour of b., as I think funny names are good. The compiler cares nothing about names, but the human mind would remember the purpose well, and a newcomer would pick it up quickly.
The second group (IFileFilter) is not good. It might get filled with a lot of methods that do file filtering.
and if it's not, I think it should reflect the intention of the implementing class.
Since multiple interfaces per class are allowed, it's ok to have specialised ones.