Local Replica Manager

1388160329_cloud_sync_synchronization_reload_refresh_updateKan brugerne selv lave en lokal replika med en selektiv replikeringsformula? Nej – det er kun de færreste superbrugere der har kendskab nok til Lotus Notes og den enkelte database til at de kan lave en selection @formula.

Men, det kan gøres nemt med Lotus Script. I vedlagte demo database klikker man blot på en knap og vælger en kategori og derefter bliver der automatisk oprettet en ny lokal replika af databasen – men kun med dokumenter fra den valgte kategori.

Det var ikke helt nemt at få til at virke – men med hjælp fra Finn Knudsen og Kenneth Badensø lykkedes det at få lavet de rigtige C api kald.

Dmeo basen kan downloades her: LRM

LotusScript Agent Manager

1388159239_Spy_user_agent_webroot_undercover_sweeper_stagFor at schedulere en agent, så skal man bruge Domino Designer. Men hvad hvis dine kunder har en hosted løsning og kun bruger Web – hvordan kan de så selv schedulere og aktivere agenter?

Der findes en simpel løsning: du aktivere og schedulere agenterne til at køre hver ½ time. Hvergang agenten kører, checker den et profil dokument og ser hvornår den burde køre. Via et web interface kan brugeren selv rette indstillingerne på profil dokumentet.

Har vedlagt et eksempel her: amgr

Replikering fra Lotus Script

1380060043_035Åben replikator siden
 Foretag en replikering
  • Call database.Replicate(server)
 Opret en ny replia
  • Set localDatabase = db.CreateReplica(“”, db.Filepath)
 Tilføj ikon til workspace (og replikator siden)
  • Call ws.Adddatabase(“”, database.Filepath)

Det kan kan evt. køres fra en baggrundsagent på klienten – så opdager brugeren ikke noget

Size to Bytes

Her en lille funktion der konvertere et tal til bytes, f.eks. bliver 12.500 til 12,2 Kbytes

Function getSize( size As Double ) As String
           Dim s As Double
           s = size
           Dim units As Variant
           units = Split( "bytes,Kb,Mb,Gb,Tb,Pb", "," )
           Dim i As Integer

           While s > 1024
                      s = s / 1024
                      i = i+1
           Wend

           getSize = Round( s, 1 ) & " " & units( i )
End Function

LorumIpsum

Med nedenstående klasse kan du nemt anonymisere en database – dvs. erstatte tekst med Lorum Ipsum og alle tal med randoms. Dette kan være nyttigt til at skabe test eller demo data

Class LorumIpsum
	Private words As Variant
	Private wordCount As double

	Sub New
		words = Split(|a,ac,accumsan,adipiscing,aliquam,aliquet,amet,ante,arcu,at,auctor,augue,aenean,bibendum,blandit,commodo,condimentum,congue,consectetur,consequat,convallis,cubilia,cursus,cras,cum,curabitur,curae;,dapibus,diam,dictum,dictumst,dignissim,dis,dolor,dui,donec,egestas,eget,eleifend,elementum,elit,enim,erat,eros,est,et,eu,euismod,etiam,facilisis,faucibus,felis,fermentum,feugiat,fringilla,fusce,gravida,habitasse,hac,hendrerit,iaculis,id,imperdiet,in,interdum,ipsum,integer,justo,lacinia,lacus,laoreet,lectus,leo,libero,ligula,lobortis,lorem,luctus,magna,magnis,malesuada,massa,mattis,mauris,metus,mi,molestie,mollis,montes,mus,maecenas,morbi,nascetur,natoque,nec,neque,nibh,nisi,nisl,non,nulla,nunc,nam,nullam,odio,orci,ornare,parturient,pellentesque,penatibus,pharetra,placerat,platea,porta,porttitor,posuere,pretium,primis,pulvinar,purus,phasellus,praesent,proin,quam,quis,quisque,rhoncus,ridiculus,risus,rutrum,sagittis,sapien,scelerisque,sed,semper,sem,sit,sociis,sodales,sollicitudin,suscipit,suspendisse,tellus,tempor,tempus,tincidunt,tortor,tristique,turpis,ullamcorper,ultrices,ultricies,urna,ut,varius,vehicula,vel,velit,venenatis,vestibulum,vitae,viverra,volutpat,vulputate,vivamus|, ",")
		wordCount = UBound( words )
		randomize
	End Sub

	Private Function getPrecision( value As Variant ) As Integer
		Dim result As Integer
		result = 0

		Dim s As String
		s = CStr( value )
		If InStr( s, "," ) > 0 Then
			getPrecision = Len( StrRight( s, "," ))
		Else
			While Right( s, 1 )="0" And Len(s ) > 2
				result = result-1
				s = Left( s, Len(s )-1 )
			Wend

			getPrecision = result
		End If
	End Function

	public Function getRandom( min As Double, max As double) As Double
		getRandom = (max-min)* rnd( 1 ) + min
	End Function

	Function randomNum( value As variant ) As Double
		Dim precision As Integer
		precision = getPrecision( value )
		value = value * getRandom( 0.2, 5 )

		randomNum = Round( value, precision )
	End Function

	Function randomString( value As String ) As String
		Dim s As String

		Dim result As Variant
		result = Split( value, " " )

		 Dim uppercase As Boolean
		 uppercase = true
		 Dim i As Integer
		 For i = 0 To UBound( result )
		 	Dim lastChar As String
		 	lastChar = right( result( i ), 1 )
		 	Dim idx As Integer
			 idx = CInt( getRandom( 0, wordCount ))
			result( i ) = words( idx )
			If uppercase Then
				result( i ) = UCase( Left( result( i ),1 )) & Mid( result( i ), 2 )
				uppercase = false
			End If

			Select Case lastchar
			Case ".":
				result( i ) = result( i ) & lastchar
				uppercase = True
			Case ",":
				result( i ) = result( i ) & lastchar
			End Select
		 Next

		 randomString = Join( result, " " )
	End Function
End Class

Links

NotesDocument datoer

datesDer findes 4 interessante datoer på et Notes Document:

  • Created in this file og Created initially
  • Modified in this file og Modified initially

Alle fire datoer kan aflæses via Lotus Script:

CreatedInitially = doc.Created
CreatedInThisFile = getAddedToFileStr( doc ).Lslocaltime
ModifiedInitially = doc.Getfirstitem("$Revisions").Lastmodified
ModifiedInThisFile = doc.Lastmodified

‘Created in this file’ datoen kræver et kald til API’et

Type TIMEDATE
	Innards(0 To 1) As Long
End Type
Declare Function ConvertTIMEDATEToText% Lib "nnotes" (ByVal IntlFormat&, ByVal TextFormat&, InputTime As TIMEDATE, ByVal retTextBuffer$, ByVal TextBufferLength%, retTextLength%)
Declare Sub NSFNoteGetInfo Lib "nnotes" (ByVal hNote&, ByVal member%, td As TIMEDATE)

Const NOTE_ADDED_TO_FILE = 13
Const MAXALPHATIMEDATE = 80

Function getAddedToFileStr(doc As NotesDocument) As NotesDateTime
	' --- This is the actual function
	Dim td As TIMEDATE
	Dim tdStr$
	Dim cbStr%
	
	' --- using hidden "Handle" property in NotesDocument class, grab TIMEDATE 
	NSFNoteGetInfo doc.Handle, NOTE_ADDED_TO_FILE, td
	
	' --- convert TIMEDATE to a string using standard "current" settings
	tdStr$ = String$(MAXALPHATIMEDATE + 1, 0)
	ConvertTIMEDATEToText 0&, 0&, td, tdStr$, MAXALPHATIMEDATE, cbStr%
	
	' --- return the NotesDateTime to the caller 
	Dim dt As New NotesDateTime( Left$(tdStr$, cbStr%) )
	Set GetAddedToFileStr = dt
End Function 

Extreme Programming (XP)

Bogen “Introduktion til Extreme Programming” af Kent Beck kan varmt anbefales.

For programmøren kan XP bedst beskrives som

  • Lav små, men ofte, releases
  • Udvikling i iterationer
  • Hvis ingen har bedt om det – så skal det ikke laves (også selvom du forventer at det skal laves senere)
  • Skriv test koden først – og test ofte (unittest og funktionalitetstest)
  • Kun arbejde indenfor normal arbejdstid – dvs. sæt kun realistiske deadlines
  • Refractor når du ser muligheden
  • Kode skal bestå alle test inden der releases
  • Keep it simple – udskud det komplekse til det bliver nødvendigt
  • Pair programming. (Personligt mener jeg ikke at pair programming er optimalt til Notes udvikling – men daglige code reviews med en kollega giver rigtig god mening)

Indenfor softwareudvikling er der fire faktorer: Omkostninger, Tid, Kvalitet og Omfang. Kunden kan/må kun bestemme de tre (men bestemmer selv hvilke) – den sidste er op til programmøren (eller teamet)

XP lægger stor vægt på at koden skal være enkel og formidlende – og ikke må indeholde gentaget kode. I bogen bliver 80/20 reglen også fremhævet:

80% af fortjenesten kommer fra 20% af indsatsen

Så derfor skal vi starte med at kode de 20% – og udskyde resten til næste release …

Scrum er i øvrigt en delmængde af XP, der fokusere på projektledelsen omkring et udviklingsprojekt.

Links