30 June 2009

Dude, where's my data access?

בהעמקת הכרותנו עם שכבת הממשק משתמש, אפשר כבר לראות את הצל של שכבת הלוגיקה המתקרבת. הגיע הזמן לקצת תכנון.

הנושא של היום הוא השאלה איפה לשים את הקוד שמפיק את שאילתותנו מול מסד הנתונים. החלטנו בשלב מוקדם יותר (ראה להלן) להשתמש ב
Linq to SQL
לשכבת ה
DAL.

LINQ to SQL,
כשגוררים עליו טבלאות ממסד נתונים של
SQL Server,
אוטומטית קורא ומפיק את היחסים בין הטבלאות שהגדרת במסד הנתונים






כששומרים את הקובץ
Linq to SQL,
מופק אוטומטית
מחלקה בשם
DataContext - הקשר-נתונים

ביחד עם כל המחלקות שצריך כדי להציג את הישויות שלך כאובייקטים, כולל יכולות שמירה וקריאה למסד הנתונים.


המחלקות שאנחנו תכלי'ס כתבנו בשכבת ה
DAL
מבצעות את הלוגיקה הכי בסיסית של
CRUD (create, retrieve, update, and delete)

על כל סוג של ישות בנפרד. אציין שככה לא צריך אף פעם לגזור מחרוזת
SQL.
ואם בנינו נכון את היחסים, אף פעם לא צריך לבנות שאילתת
Linq
שמשמתמש ב
join.
המחלקות שיצר לנו את מחלקת ההקשר-נתונים אמורים לעשות לנו את כל העבודה.

היופי בזה הוא בכך שאם יש לי ביד ישות "בנאדם" או אוסף שלהן, כל עוד שהוא מקושר למחלקת ההקשר-נתונים (ז"א, לא עבר תהליך סריליזציה - נושא לכניסה אחרת) אפשר "למשוך" על מספרי הטלפון של הבנאדם (עם זו פעם הראשונה למופע הזה, לפחות) ואז הוא יבצע שאילתא מול מסד הנתונים ויוציא את המידע הצריך.

והינה השאלה של היום: כמה מהמשיכה הזו נכון לעשות בשכבת הלוגיקה?

פרט זה, של מתי מתבצע השאילתא, זה לא ענין, אלא איזה קוד אחראי על ביצועו. לכן אם קוד מופק אוטומטית של הקשר-נתונים נמצא בשכבת ה
DAL
וקיימת שורה בשכבת הלוגיקה שגורמת לו להתבצע, האם שברנו אף חוק של תכנות ב3 שכבות? נדמה לי שלא. ואם נחליט בתאריך מאוחר יותר להשתמש בטכנולוגיה אחרת בשכבת ה
DAL,
נוכל לספק מחלקות שמחשפות אובייקטים מיוחסים כמו אלה של
Linq to SQL.
ושכבת הלוגיקה לא צריכה אף פעם לדאוג מתי נקרא המידע ממסד הנתונים.

-------------------------------------------------

As we dig deeper into the UI layer, the ghostlike form of the Business Logic layer (BL) is peering out at us from the future. A little planning is in order.

Today's issue is the question of where to place the code that generates our queries on the DB. We decided at an early stage (see below) to use LINQ to SQL for our Data Access layer (DAL).

LINQ to SQL, when you drag tables from an SQL Server database onto it, automatically reads and generates the existing relationships between your tables.








When you then save your LINQ to SQL class, called a DataContext, it autogenerates a code file with all the classes necessary to

1) represent your data entities in your program as business entities

2) persist your entities to the database




The classes we wrote for the DAL do the very barest CRUD logic (create, retrieve, update, and delete) on one entity type at a time. Note that with LINQ to SQL, we need not ever write a single SQL string. If we built the relationships correctly, furthermore, we need not ever write a single LINQ query with a "join" - because the DataContext should be doing that all for us.

The beauty of LINQ is that once I have a Person or collection of Persons, as long as it is still attached to the generating DataContext (that means it has never been serialized and deserialized... a topic for a different post), I can pull on Person.Phones and that will (the first time I call it for this instance) query the database for the phone objects related to the person at hand.

And so, the question: how much of this pulling can responsibly be done in the BL?

The detail of when the query is executed is not an issue, it's only a question of which code is reponsible for doing it. So if the autogenerated code for the DataContext is in the DAL, and a line in the BL causes it to fire and query the DB, have we violated any priciple of 3-layered structure? I don't think we have. And if we decide at some later date to use LINQ to Entities or some other mechanism in our DAL, we can provide classes that expose the related objects just as well as LINQ to SQL does. And the BL need never worry about when the data is read from the DB.

29 June 2009

Not a member? Join today!

הגיע הזמן להפיק גירסה ראשונית לממשק משתמש. לאפליקציה אינטרנטית כמו שלנו, צריך לשאול: איך נטפל בזיהוי משתמשים, דוגמת רישום וכניסה למשתמש מוכר?

ASP.net
אמור לטפל בנושאים כאלה עם מה שנקרא "חברות" (תרגום
.(membership

אם המתכנת הוא אצלן (זה בעצם יכול להיות דבר טוב) אז סביבת הפיתוח יכול להפיק לו מסד נתונים מוסתר בשם
aspnetdb.mdf
בתיקיית ה
App_Data,
ודרך קריאות למחלקה מוסתרת שומרת נתונים לתוכו. דף לוקלי פותחים ישיר מהתפריט של סביבת הפיתוח שנותן לנהל את המשתמשים המוכרים כבר בזמן תכנון.






משפחת פקדים
login
שמגיע מוכן עם
.NET 3.5
משתמשים בכל זה באופן ישיר. ומהקוד שלך, תוכל בקלות לבדוק האם המשתמש הנוכחי נכנס למערכת רשמי כמשתמש מוכר ופרטים נוספים מהסטטוס ה"חברתי" שלו.





מה בזה לא טוב לנו?

משפחת הפקדים הזו מבוססת על הכלת מסד הנתונים המוסתרת שם בדיוק בתוך שכבת הממשק משתמש, גבר שמונע ממך למשוך נתוני משתמש ממסד הנתונים שלך. בנוסף, זה שובר את מודל ה3 שכבות. סה"כ, לא בתוכניות המקוריות שלנו.

אפשר לתת לספק החברות (מחלקה שמנהלת חברות) מאיפה למשוך את הנתונים... אבל אז אתה משנה את ההגדרות לספק החברות שנמצאות ב
machine.config
ע"י הוספת עצמים ל
web.config
ואז מבנה הטבלאות שלך חייב להתאים לדרישות של ספק החברות המוכן. ויתר על כן, מסד הנתונים שלך חייב להימצא בשכבת ממשק המשתמש. עדיין לא 3 שכבות, עדיין לא מצא חן בעינינו.

במחיר הרבה עבודה מיותרת, נוכל לממש ספק חברות משלנו וגם (הודו לה') לשמור על מבנה ה3 שכבות וגם להשתמש בפקדים המוכנים. זה מוצא חן בעינינו, בגלל שלבסוף רוב הקוד שאנחנו כותבות לספק חברות שלנו מהווה פונקציונליות נחוץ כדי ליצור אתר אינטרנט עם זיהוי משתמשים מספקת. ולאור חוסר נסיון שלנו בזיהוי משתמשים, נשמח לקבל הגדרות קשיחות ממיקרוסופט.

נקודה אחרונה: פקדים ממשפחת
login
שוברות את
MVC.
אבל המטרה של דגם תכנון הוא להיות כלי, לא להיות מחסום - אז אם צריך, נשבור!


--------------------------------------------

The time has come to produce a version of the UI. For a web application like ours, we must answer the question: how do we handle user authentication (eg, registration and login) ?

ASP.net is designed to deal with these issues with what it calls "membership".

If the programmer is really lazy (this can be a good thing), ASP.net will generate an invisible database called aspnetdb.mdf in your App_Data folder and invisibly call on a class to persist to that database. A (local) web page that opens directly from the menu in Visual Studio allows you to manage the users from this database at design time.






The Login family of controls provided by ASP.net plug directly into this system. And from your code, you can easily check if the current user is logged in and other details of his "membership" status.





What about this don't we want?

The Login family of controls provided by ASP.net are based on inclusion of the (invisible) database right there in your UI layer, which means that user data is not coming from your own database. Additionally, this is not in keeping with the 3-layered look. Altogether, not part of our original plans. You can tell the membership provider where its database is... but then you're overriding the default provider datastore defined in machine.config by adding elements to web.config, and then your table structure has to be exactly what the canned membership provider is expecting. And, of course, the membership provider is in the UI, so your database must be there, too. Still not 3 layers, still pretty evil.

For the price of lots of extra work, we can implement our own membership provider class and (oh, joy) still preserve the 3 layers AND use Microsoft's Login controls. This is good, because ultimately the vast majority of the code we're writing for our customized membership provider is functionality we need in order to have a website with sufficient authentication. And, as we have little to no experience with authentication, if Microsoft is dictating what our authentication class needs to support, we're more likely to reach our destination.

A final point: the Login controls will never work with MVC. But MVC is a tool for us, not a prison - so when it serves us to break it, we will!

23 June 2009

Human Events: A Sequel to Yesterday's Post

After we took two months to generate documentation that was expected in a few weeks, our client seems understandably unwilling to meet with us.

Did we take too long? Of course. Why? Because the work was so difficult for us. Drawing up a large set of statecharts or use-case diagrams is not difficult work, and it's useful in helping the programmer think through the scenarios he needs to handle. Writing up a list of possible screens, possible behaviors, and possible messages is tedious, difficult work to someone who is used to modeling in a graphic language.

What would have happened if we had refused to write such extensive, formal documentation? Could it have been worse than the current situation? Maybe the situation now is salvageable. Maybe then it wouldn't have been? I think we should have negotiated a different form of documentation from the first. Now we're going to have to crawl...

22 June 2009

Human Communications

עם כל התיעוד שנאלצנו לכתוב, אני נזכרת בשני ספרים נהדרים:
The Elements of Style
מאת

William Strunk Jr, E.B. White,
The Visual Display of Quantitative Information
מאת
Edward Tufte.
ברצוני לדעת: האם באמת בכל המטרים של ניירת שאנחנו מפיקות יש מידע משמעותי שמגיע לצד השני? האם המסר שלנו ברור? האם אפילו אצלינו הוא ברור?

אומרים לסטודנטים (שהם אנחנו) שתיעוד הוא חלק חיוני מתהליך הפיתוח, ובמיוחד כשקיימים כמה גורמים עם מטרות שונות ובעלי רקעים שונים, דוגמת צורכים סופיים ומתכנתים. תהליך פיתוח נכון מבחינה זו, לטענת המרצים, ישפיע על הסיכויים שהפרויקט שלך לא יתקל בבאגים בלתי-פתירים בשלב מאוחר ביותר בפיתוח, וגם שלא יופק מוצר שלא יקובל ע"י הלקוח בגלל שהוא לא מספק את דרישותיו.

אבל האם זה נכון? עריכת התיעוד דרש לנו בערך חודשיים, בהם לא התקדמנו בתכנון או בקידוד. רוב הבעיה היתה בזה שהסגנון אותו דרש הלקוח למסמך שלנו לא תאם בכלל לסגנון החשיבה לו אנחנו מורגלות. יתכן שזה הדרך הכי יעיל לוודא שעובדים נכון? באיזה מכיר? ולאור העובדה שעקמנו בחשיבה כל כך כדי להפיק את התיעוד הזה, איזה סיכוי יש לנו להפיק קוד שיתאים לו?

כשהשיטה נהיתה כל כך אי-טבעי וכואב, אני משוכנעת שחייב להיות קיים שיטה טובה יותר

--------------------------------

With all the documentation we're being induced to write, I am reminded of two works: Strunk and White's Elements of Style, and Tufte's Visual Display of Quantitative Information. I wonder, in all the meters of ink on paper we're churning out, how much data is really getting through to the other side. I wonder if our message is clear. I wonder if we even have much message to deliver.

Documentation, we are informed as students, is a necessary part of the software development process where multiple parties with multiple interests and background fields are involved (eg, shareholders and programmers). Proper software development process, they tell us, will help save your project from being so error-prone as to be useless or so far from satisfying your end user as to be rejected.

Is this true? Documentation kept us away from design and code for about two months. This was mostly because drafting documentation to meet the standards set by our client company was completely foreign to our thought patterns. Can this really be the best way to ensure that we're doing it right? At what expense? And considering how far we had to bend our thought patterns to plan and design in this way, how likely is it that we will succeed in actually delivering a product that conforms with what we described?

When the method gets so painfully unnatural, I am convinced that there must be a better way.

21 June 2009

Introducing a Project

עכשיו כשאנחנו סופסוף מתחילות לקודד את הפרויקט הסופי (אפילו אם זה התחלה מוטעה, מתקרבים) ברצוני לשמור אזכרה לדברים המגניבים שנעשה. ויתר על כן, אני רוצה לשמור אזכרה לדברים המגניבים שלא נעשה לאחר שמנסים אותם, בגלל שדברים כאלה לא יופיעו לנו בפרויקט הסופי והם עדיין מגניבים.

קודם כל תיאור קצר של הפרויקט:
אנחנו מפתחות אתר אינטרנט לחברה קיימת (לא האתר הראשי שלהם) בשימוש מסד הנתונים והשרתים שלהם. לפי בקשתם, אנחנו כותבות מסמכים שונים בכל שלב התכנון, דבר שמאיט אותנו בצורה משמעותית למדי. לדעתי כדאי לנו לצמצם בדוקומנטציה בהמשך (?).
הדגש בפרויקט אמור להיות בחווית משתמש חלקה ושימוש יעיל בנתונים
(OLAP).

רשימת סיכום דברים מגניבים שעד עכשיו הסכמנו לא לעשות:
ASP.net MVC
EDM
Data controls

רשימת סיכום דברים מגניבים שככל הנראה כן נעשה:
MVC - מימוש שלנו, לא של מיקרוסופט
WCF
AJAX
אלגוריתמים - למצוא העדפות של המשתמשים

--------------

Now that we're really starting to code our final project (at least, even if it's a false start, we're getting very close) I want to start a record of the cool stuff we do. More importantly, I want to record the cool stuff we decide not to do after trying it, because those things won't show up in our final project but still deserve to be remembered.

A brief description of the project is in order:
we are developing a website for an existing company (not their flagship website), using their databases and their servers. By their request, we are writing documentation at intervals, but this documentation slows us down to a near-standstill. I think we should refuse to write documentation in the future, except in very limited measures. (?)
The emphasis of the project is supposed to be a smooth user experience and efficient use of data (by way of OLAP).

A summary of cool things we probably won't be doing:
ASP.net MVC - as we know nothing of unit testing, which seems to be its sole advantage
EDM - we still haven't figured out why we would want this instead of LINQ to SQL
Data controls - objects in the business layer vs easy binding in UI? Business layer wins

Cool things we probably will be doing:
MVC - implemented by us, not by the developers of C#
WCF
AJAX
Algorithms - to determine user preferences

Now let's see what my partners are up to with their parts of the DAL...